I have a function that deletes the smallest node in a doubly-linked list. But if there are more than one same-valued integers, the function deletes the first one. I need to do, that function deletes all the smallest values.
I think I need to make a loop, to check all the values in the linked list and delete them if they are == to the smallest one.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
struct node *prev;
int number;
struct node *next;
} node;
node *createList(struct node *head, int n);
node *addToEmpty(node *head, int data);
node *addAtEnd(node *head, int data);
node *deleteSmallest(node *head, int n);
void cleanUp(node *head);
int main()
{
node *head = NULL;
node *ptr;
int n;
printf("Enter number of the nodes: ");
scanf("%d", &n);
head = createList(head, n);
printf("\nN: %d\n\n", n);
ptr = head;
while(ptr != NULL)
{
printf("NUMBER:%d ADDRESS:%p PREVADD:%p NEXTADD:%p\n", ptr->number, ptr, ptr->prev, ptr->next);
ptr = ptr->next;
}
head = deleteSmallest(head, n);
printf("\n\n");
ptr = head;
while(ptr != NULL)
{
printf("NUMBER:%d ADDRESS:%p PREVADD:%p NEXTADD:%p\n", ptr->number, ptr, ptr->prev, ptr->next);
ptr = ptr->next;
}
// Free all the pointers
cleanUp(head);
return 0;
}
node *createList(struct node *head, int n)
{
int data;
if(n <= 0)
return head;
printf("Enter number of the 1 node: ");
scanf("%d", &data);
head = addToEmpty(head, data);
for(int i = 1; i < n; ++i)
{
printf("Enter number of the %d node: ", i + 1);
scanf("%d", &data);
head = addAtEnd(head, data);
}
return head;
}
node *addToEmpty(node *head, int data)
{
node *temp = malloc(sizeof(node));
temp->prev = NULL;
temp->next = NULL;
temp->number = data;
head = temp;
return head;
}
node *addAtEnd(node *head, int data)
{
node *temp, *tp;
temp = malloc(sizeof(node));
temp->prev = NULL;
temp->next = NULL;
temp->number = data;
tp = head;
while (tp->next != NULL)
tp = tp->next;
tp->next = temp;
temp->prev = tp;
return head;
}
node *deleteSmallest(node *head, int n)
{
node *smallest, *temp, *temporaryHead;
int position = 1;
temporaryHead = head;
smallest = head;
// Finding which node has the smallest int
for(int i = 1; temporaryHead != NULL; ++i)
{
temp = temporaryHead->next;
if(smallest->number > temporaryHead->number)
{
smallest = temporaryHead;
position = i;
}
temporaryHead = temp;
}
temporaryHead = NULL;
temp = head;
// If node is in the middle
if(position > 1 && position < n)
{
while (position > 1) {
temp = temp->next;
--position;
}
temporaryHead = temp->prev;
temporaryHead->next = temp->next;
temp->next->prev = temporaryHead;
free(temp);
temp = NULL;
}else if(position == 1) // If node is the first element
{
head = head->next;
free(head->prev);
head->prev = NULL;
}else // If node is the last element
{
while(temp->next != NULL)
temp = temp->next;
temporaryHead = temp->prev;
temporaryHead->next = NULL;
free(temp);
temp = NULL;
}
return head;
}
void cleanUp(node *head)
{
node *next;
while(head != NULL)
{
next = head->next;
free(head);
head = next;
}
}
I think I need to make a loop, to check all the values in the linked list and delete them if they are == to the smallest one.
I didn't quite understand the logic of your current function (particularly, the n argument).
Here is a function that will allow just one element to be removed or all matching smallest elements. If there is only one it is a single scan pass. If there are more, it is just two scan passes:
// deleteSmallAll -- delete all nodes that are the smallest
node *
deleteSmallAll(node *head,int allflg)
// allflg -- 1=delete all, 0=delete first
{
node *small = head;
int smcount = 0;
int smnum = 0;
node *cur = head;
// skip over the first element (and assume it is the smallest)
if (cur != NULL) {
cur = cur->next;
smcount = 1;
smnum = small->number;
}
// find the smallest
for (; cur != NULL; cur = cur->next) {
int curnum = cur->number;
// got a smaller element
if (curnum < smnum) {
smcount = 1;
small = cur;
smnum = curnum;
continue;
}
// keep count of duplicate small numbers
if (curnum == smnum) {
if (allflg)
smcount += 1;
continue;
}
}
// start with the _first_ smallest node we found
cur = small;
// remove a single smallest and loop if more to do
while (cur != NULL) {
node *next = cur->next;
node *prev = cur->prev;
// unlink it
if (prev != NULL)
prev->next = next;
else
head = next;
// unlink it
if (next != NULL)
next->prev = prev;
// NOTE: no tail pointer
#if 0
else
tail = prev;
#endif
// release the node
free(cur);
// bug out if no more of that match
if (--smcount <= 0)
break;
// find the next in the list that is the same match
for (cur = next; cur != NULL; cur = cur->next) {
if (cur->number == smnum)
break;
}
}
return head;
}
UPDATE:
Hopefully, you've gotten an answer for your basic question.
But, as others pointed out, what's the point to have a doubly linked list if you only traverse it in the forward direction?
Below is an updated version. It uses a separate list struct and passes a pointer to that instead of passing in head and always returning the updated value.
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
typedef struct node {
struct node *prev;
int number;
struct node *next;
} node;
typedef struct {
node *head;
node *tail;
} list;
int
getnum(const char *prompt)
{
char buf[100];
int data = 0;
// debug hook for input from redirected file (e.g. ./myprogram < input.txt)
struct termios tio;
int fileflg = tcgetattr(fileno(stdin),&tio) < 0;
while (1) {
printf("%s: ",prompt);
fflush(stdout);
if (fgets(buf,sizeof(buf),stdin) == NULL) {
printf("getnum: premature EOF\n");
if (fileflg)
exit(1);
}
// echo the file input
if (fileflg)
fputs(buf,stdout);
if (sscanf(buf,"%d",&data) == 1)
break;
}
return data;
}
void
addAtEnd(list *lst, int data)
{
node *temp;
temp = malloc(sizeof(node));
temp->number = data;
if (lst->head == NULL)
lst->head = temp;
node *tail = lst->tail;
if (tail != NULL) {
temp->next = tail->next;
tail->next = temp;
temp->prev = tail;
}
else
temp->prev = NULL;
lst->tail = temp;
temp->next = NULL;
}
void
createList(list *lst, int n)
{
int data;
char msg[100];
for (int i = 0; i < n; ++i) {
sprintf(msg,"Enter number of the %d node", i + 1);
data = getnum(msg);
addAtEnd(lst, data);
}
}
// deleteSmallAll -- delete all nodes that are the smallest
void
deleteSmallAll(list *lst,int allflg)
// allflg -- 1=delete all, 0=delete first
{
node *small = lst->head;
int smcount = 0;
int smnum = 0;
node *cur = lst->head;
// skip over the first element (and assume it is the smallest)
if (cur != NULL) {
smcount = 1;
smnum = small->number;
cur = cur->next;
}
// find the smallest
for (; cur != NULL; cur = cur->next) {
int curnum = cur->number;
// got a smaller element
if (curnum < smnum) {
smcount = 1;
small = cur;
smnum = curnum;
continue;
}
// keep count of duplicate small numbers
if (curnum == smnum) {
if (allflg)
smcount += 1;
continue;
}
}
// start with the _first_ smallest node we found
cur = small;
// remove a single smallest and loop if more to do
while (cur != NULL) {
node *next = cur->next;
node *prev = cur->prev;
// unlink it
if (prev != NULL)
prev->next = next;
else
lst->head = next;
// unlink it
if (next != NULL)
next->prev = prev;
else
lst->tail = prev;
// release the node
free(cur);
// bug out if no more of that match
if (--smcount <= 0)
break;
// find the next in the list that is the same match
for (cur = next; cur != NULL; cur = cur->next) {
if (cur->number == smnum)
break;
}
}
}
void
cleanUp(list *lst)
{
node *next;
for (node *cur = lst->head; cur != NULL; cur = next) {
next = cur->next;
free(cur);
}
lst->head = NULL;
lst->tail = NULL;
}
void
print_fwd(list *lst,const char *msg)
{
node *ptr = lst->head;
printf("\n%s:\n",msg);
for (; ptr != NULL; ptr = ptr->next)
printf("NUMBER:%d ADDRESS:%p PREVADD:%p NEXTADD:%p\n",
ptr->number, ptr, ptr->prev, ptr->next);
}
void
print_bwd(list *lst,const char *msg)
{
node *ptr = lst->tail;
printf("\n%s:\n",msg);
for (; ptr != NULL; ptr = ptr->prev)
printf("NUMBER:%d ADDRESS:%p PREVADD:%p NEXTADD:%p\n",
ptr->number, ptr, ptr->prev, ptr->next);
}
int
main(void)
{
list lstx = { NULL, NULL };
list *lst = &lstx;
node *ptr;
int n;
n = getnum("Enter number of the nodes");
createList(lst, n);
printf("\nN: %d\n", n);
print_fwd(lst,"orig/fwd");
print_bwd(lst,"orig/bwd");
deleteSmallAll(lst, 0);
print_fwd(lst,"after1/fwd");
print_bwd(lst,"after1/bwd");
deleteSmallAll(lst, 1);
print_fwd(lst,"afterN/fwd");
print_bwd(lst,"afterN/bwd");
// Free all the pointers
cleanUp(lst);
return 0;
}
Here is the sample input:
6
2
6
2
7
8
2
Here is the sample output:
Enter number of the nodes: 6
Enter number of the 1 node: 2
Enter number of the 2 node: 6
Enter number of the 3 node: 2
Enter number of the 4 node: 7
Enter number of the 5 node: 8
Enter number of the 6 node: 2
N: 6
orig/fwd:
NUMBER:2 ADDRESS:0x11a4280 PREVADD:(nil) NEXTADD:0x11a42a0
NUMBER:6 ADDRESS:0x11a42a0 PREVADD:0x11a4280 NEXTADD:0x11a42c0
NUMBER:2 ADDRESS:0x11a42c0 PREVADD:0x11a42a0 NEXTADD:0x11a42e0
NUMBER:7 ADDRESS:0x11a42e0 PREVADD:0x11a42c0 NEXTADD:0x11a4300
NUMBER:8 ADDRESS:0x11a4300 PREVADD:0x11a42e0 NEXTADD:0x11a4320
NUMBER:2 ADDRESS:0x11a4320 PREVADD:0x11a4300 NEXTADD:(nil)
orig/bwd:
NUMBER:2 ADDRESS:0x11a4320 PREVADD:0x11a4300 NEXTADD:(nil)
NUMBER:8 ADDRESS:0x11a4300 PREVADD:0x11a42e0 NEXTADD:0x11a4320
NUMBER:7 ADDRESS:0x11a42e0 PREVADD:0x11a42c0 NEXTADD:0x11a4300
NUMBER:2 ADDRESS:0x11a42c0 PREVADD:0x11a42a0 NEXTADD:0x11a42e0
NUMBER:6 ADDRESS:0x11a42a0 PREVADD:0x11a4280 NEXTADD:0x11a42c0
NUMBER:2 ADDRESS:0x11a4280 PREVADD:(nil) NEXTADD:0x11a42a0
after1/fwd:
NUMBER:6 ADDRESS:0x11a42a0 PREVADD:(nil) NEXTADD:0x11a42c0
NUMBER:2 ADDRESS:0x11a42c0 PREVADD:0x11a42a0 NEXTADD:0x11a42e0
NUMBER:7 ADDRESS:0x11a42e0 PREVADD:0x11a42c0 NEXTADD:0x11a4300
NUMBER:8 ADDRESS:0x11a4300 PREVADD:0x11a42e0 NEXTADD:0x11a4320
NUMBER:2 ADDRESS:0x11a4320 PREVADD:0x11a4300 NEXTADD:(nil)
after1/bwd:
NUMBER:2 ADDRESS:0x11a4320 PREVADD:0x11a4300 NEXTADD:(nil)
NUMBER:8 ADDRESS:0x11a4300 PREVADD:0x11a42e0 NEXTADD:0x11a4320
NUMBER:7 ADDRESS:0x11a42e0 PREVADD:0x11a42c0 NEXTADD:0x11a4300
NUMBER:2 ADDRESS:0x11a42c0 PREVADD:0x11a42a0 NEXTADD:0x11a42e0
NUMBER:6 ADDRESS:0x11a42a0 PREVADD:(nil) NEXTADD:0x11a42c0
afterN/fwd:
NUMBER:6 ADDRESS:0x11a42a0 PREVADD:(nil) NEXTADD:0x11a42e0
NUMBER:7 ADDRESS:0x11a42e0 PREVADD:0x11a42a0 NEXTADD:0x11a4300
NUMBER:8 ADDRESS:0x11a4300 PREVADD:0x11a42e0 NEXTADD:(nil)
afterN/bwd:
NUMBER:8 ADDRESS:0x11a4300 PREVADD:0x11a42e0 NEXTADD:(nil)
NUMBER:7 ADDRESS:0x11a42e0 PREVADD:0x11a42a0 NEXTADD:0x11a4300
NUMBER:6 ADDRESS:0x11a42a0 PREVADD:(nil) NEXTADD:0x11a42e0
I would split the logic into parts:
A function to find the least value (an integer) in a list
A function to delete nodes from a list that have a given value
Use the above two functions to implement deleteSmallest
Here is how that could look:
int getSmallestValue(node *head) {
int smallest = head == NULL ? 0 : head->number;
while (head != NULL) {
if (head->number < smallest) {
smallest = head->number;
}
head = head->next;
}
return smallest;
}
node* deleteValue(node *head, int n) {
node* temp, *current;
while (head != NULL && head->number == n) {
temp = head;
head = head->next;
free(temp);
}
head->prev = NULL;
current = head->next;
while (current != NULL) {
temp = current;
current = current->next;
if (temp->number == n) {
temp->prev->next = current;
if (current != NULL) {
current->prev = temp->prev;
}
free(temp);
}
}
return head;
}
node *deleteSmallest(node *head, int n) {
return deleteValues(head, getSmallestValue(head));
}
If you were concerned about performance, instead of addAtEnd(), you might have addToFront(). This would reduce the asymptotic time from O(n^2) to O(n) to input the numbers.
If you must delete-minimum again and again, a linked-list is not really a good fit. As you have observed, all the input must be traversed if one wants to find the minimum, which takes O(n) each time. In this case, a binary heap would allow O(log n) delete-minimum. It does this by heapify, in which the heap is created by sifting down in O(n), and maintaining the heap property of each int is less than or equal to the int's children.
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
static void int_to_string(const int *i, char (*const a)[12])
{ sprintf(*a, "%d", *i); }
#define HEAP_NAME int
#define HEAP_TYPE int
#define HEAP_TO_STRING
#include "heap.h"
int main(int argc, char **argv) {
struct int_heap ints = int_heap();
size_t n = 0;
int success = EXIT_SUCCESS;
(void)argc; /* Don't use. */
while(*++argv) { /* Get command line arguments. */
long argl;
char *end;
int *a;
argl = strtol(*argv, &end, 0); /* Convert to `long`. */
if(argl < INT_MIN || argl > INT_MAX || end == *argv || *end != '\0')
{ if(!errno) errno = ERANGE; goto catch; }
if(!(a = int_heap_buffer(&ints, n + 1))) goto catch;
a[n++] = (int)argl;
}
int_heap_append(&ints, n); /* Heapifies, O(n), <Floyd, 1964, Treesort>. */
while(ints.as_array.size) printf("pop: %d, remainder: %s\n",
int_heap_pop(&ints), int_heap_to_string(&ints));
printf("empty\n");
goto finally;
catch:
success = EXIT_FAILURE;
perror("count");
finally:
int_heap_(&ints);
return success;
}
I have used my implementation of a binary heap, which I've tried to make pretty standard. This is close to what heapsort does.
Related
i have a simple linked list that looks like this
typedef struct Node {
void *data;
struct Node *next
} Node;
typedef struct Node {
Node *head;
Node *tail;
int size;
} LinkedList
And my add_node function looks like this :
void add_nth_node(LinkedList *list, int n, void *new_data) {
Node *prev, *curr;
Node *new_node;
if (list == NULL) {
return;
}
/* n >= list->size inseamna adaugarea unui nou nod la finalul listei. */
if (n > list->size) {
n = list->size;
} else if (n < 0) {
return;
}
curr = list->head;
prev = NULL;
while (n > 0) {
prev = curr;
curr = curr->next;
--n;
}
new_node = malloc(sizeof(Node));
if (new_node == NULL) {
perror("Not enough memory to add element!");
exit(-1);
}
new_node->data = new_data;
new_node->next = curr;
if (prev == NULL) {
/* Adica n == 0. */
list->head = new_node;
} else {
prev->next = new_node;
}
if (new_node->next == NULL) {
list->tail = new_node;
}
list->size++;
There is something weird when i try to add nodes to the list.
When i add them like this :
int i;
for (i = 0; i < 10; i++) {
add_nth_node(list, i, &i);
}
But when i add elements like this :
int i, v[10];
for(i = 0; i < 10; i++) {
v[i] = i;
add_nth_node(list_1, i, &v[i]);
}
Everything is working as expected. Why is that ?
Why do i have to put elements is a vector first to add them to the list.
add_nth_node(list, i, &i) // (1)
// and
add_nth_node(list_1, i, &v[i]); // (2)
They are not the same but the value of data that you assign for each node is the same in two options.
(1) You make the pointer point to address of i.
(2) You make the pointer point to address of v[i].
Use (1) is very bad idea because, in this case all data of all nodes point to the same address. So if the data of one node changes, the data of all nodes change the value.
Hi this is the code I wrote for create as many nodes as he needs (the m variable), but I noticed that using this method I'm creating one more node. What's the best way of fcreating as many nodes as the user say us?
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
int val;
int rip;
struct Node *next;
} node;
node *modify(node *head);
void print(node *head2);
int main(){
int m, i;
printf("How many nodes: \n");
scanf("%d", &m);
node *head = NULL;
head = (node *)malloc(sizeof(node));
node *temp = head;
node *head2 = NULL;
printf("Write the value in HEAD position : \n");
scanf("%d", &temp->val);
temp->rip=0;
temp->next = NULL;
for(i=0; i < m-1; i++)
{
temp->next = (node *)malloc(sizeof(node));
printf("Write the value in position %d: \n", i);
temp = temp->next;
scanf("%d", &temp->val);
temp->rip=0;
temp->next = NULL;
}
head2 = modify(head);
print(head2);
return 0;
}
node *modify(node *head){
int counter, pass, m;
node *curr = head;
node *track = head;
node *precNode;
while (track != NULL){
counter = 0;
pass = 0;
m = track->val;
while( curr != NULL){
if(m == (curr)->val){
pass++;
counter++;
if(pass > 1){
node *removed = curr;
precNode->next = (curr)->next;
curr = (curr)->next;
free(removed);
}
if(pass == 1)
{
precNode = curr;
curr = curr->next;
}
}
else{
precNode = curr;
curr = (curr)->next;
}
}
track->rip = counter;
track = track->next;
curr = track;
}
return head;
}
void print(node *head2){
while(head2 != NULL){
printf("[%d, %d] -> ", head2->val, head2->rip);
head2 = head2->next;
}
printf("\n");
}
```
#include <stdio.h>
#include <stdlib.h>
//////////////////////////////////////////////////////////////////////////////////
typedef struct _listnode
{
int item;
struct _listnode *next;
} ListNode; // You should not change the definition of ListNode
typedef struct _linkedlist
{
int size;
ListNode *head;
} LinkedList; // You should not change the definition of LinkedList
//////////////////////// function prototypes /////////////////////////////////////
void moveOddItemsToBack(LinkedList *ll);
void printList(LinkedList *ll);
void removeAllItems(LinkedList *ll);
ListNode * findNode(LinkedList *ll, int index);
int insertNode(LinkedList *ll, int index, int value);
int removeNode(LinkedList *ll, int index);
void appendNode(LinkedList *ll, int item);
//////////////////////////// main() //////////////////////////////////////////////
int main()
{
LinkedList ll;
int c, i, j;
c = 1;
//Initialize the linked list 1 as an empty linked list
ll.head = NULL;
ll.size = 0;
printf("1: Insert an integer to the linked list:\n");
printf("2: Moves all odd integers to the back of the linked list:\n");
printf("0: Quit:\n");
while (c != 0)
{
printf("Please input your choice(1/2/0): ");
scanf("%d", &c);
switch (c)
{
case 1:
printf("Input an integer that you want to add to the linked list: ");
scanf("%d", &i);
j = insertNode(&ll, ll.size, i);
printf("The resulting Linked List is: ");
printList(&ll);
break;
case 2:
moveOddItemsToBack(&ll); // You need to code this function
printf("The resulting Linked List after moving odd integers to the back of the Linked List is: ");
printList(&ll);
removeAllItems(&ll);
break;
case 0:
removeAllItems(&ll);
break;
default:
printf("Choice unknown;\n");
break;
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////////
void moveOddItemsToBack(LinkedList *ll)
{
ListNode *cur , *tail, *pre ;
/* Get tail ptr to the last node */
tail = ll->head ;
while (tail->next != NULL)
tail = tail->next ;
ListNode *newTail = tail ;
newTail = tail ;
/* Start traversing list and put all odd items to tail */
cur = ll->head ;
pre = cur ;
while (cur != tail){
if(cur->item % 2 != 0) { // <- Segmentation Fault!
pre->next = cur->next ;
newTail->next = cur ;
newTail->next->next = NULL ;
cur = pre->next ;
newTail = newTail->next ;
}
else {
pre = cur ;
cur = cur->next ;
}
}
}
void appendNode(LinkedList *ll , int item){
/* Insert Node to empty list */
ListNode *cur;
if (ll->head == NULL ) {
ll->head = malloc(sizeof(ListNode));
ll->head->item = item ;
ll->size++ ;
}
cur = ll->head ;
/* Append to non-empty */
if (ll->head != NULL ) {
while (cur->next != NULL) {
cur = cur->next ;
}
cur->next = malloc(sizeof(ListNode)) ;
cur->next->item = item ;
ll->size++ ;
}
}
//////////////////////////////////////////////////////////////////////////////////
void printList(LinkedList *ll){
ListNode *cur;
if (ll == NULL)
return;
cur = ll->head;
if (cur == NULL)
printf("Empty");
while (cur != NULL)
{
printf("%d ", cur->item);
cur = cur->next;
}
printf("\n");
}
void removeAllItems(LinkedList *ll)
{
ListNode *cur = ll->head;
ListNode *tmp;
while (cur != NULL){
tmp = cur->next;
free(cur);
cur = tmp;
}
ll->head = NULL;
ll->size = 0;
}
ListNode * findNode(LinkedList *ll, int index){
ListNode *temp;
if (ll == NULL || index < 0 || index >= ll->size)
return NULL;
temp = ll->head;
if (temp == NULL || index < 0)
return NULL;
while (index > 0){
temp = temp->next;
if (temp == NULL)
return NULL;
index--;
}
return temp;
}
int insertNode(LinkedList *ll, int index, int value){
ListNode *pre, *cur;
if (ll == NULL || index < 0 || index > ll->size + 1)
return -1;
// If empty list or inserting first node, need to update head pointer
if (ll->head == NULL || index == 0){
cur = ll->head;
ll->head = malloc(sizeof(ListNode));
ll->head->item = value;
ll->head->next = cur;
ll->size++;
return 0;
}
// Find the nodes before and at the target position
// Create a new node and reconnect the links
if ((pre = findNode(ll, index - 1)) != NULL){
cur = pre->next;
pre->next = malloc(sizeof(ListNode));
pre->next->item = value;
pre->next->next = cur;
ll->size++;
return 0;
}
return -1;
}
int removeNode(LinkedList *ll, int index){
ListNode *pre, *cur;
// Highest index we can remove is size-1
if (ll == NULL || index < 0 || index >= ll->size)
return -1;
// If removing first node, need to update head pointer
if (index == 0){
cur = ll->head->next;
free(ll->head);
ll->head = cur;
ll->size--;
return 0;
}
// Find the nodes before and after the target position
// Free the target node and reconnect the links
if ((pre = findNode(ll, index - 1)) != NULL){
if (pre->next == NULL)
return -1;
cur = pre->next;
pre->next = cur->next;
free(cur);
ll->size--;
return 0;
}
return -1;
}
The above is my code, I am trying to achieve
If the linked list is 2 3 4 7 15 18:
The resulting Linked List after moving odd integers to the back of the Linked List is: 2 4 18 3 7 15
by moving all Odd items to the back of the Linked list.
The function of interest would be void moveOddItemsToBack.
I am very confused, as when I use the example given above, 2,3,4,7,15,18. I am able to get the desired output.
However, using an example such as 1,3,4,7,15,18, where the first number is an odd number, i get a segmentation fault at this line.
while (cur != tail){
if(cur->item % 2 != 0) { // <- Segmentation Fault!
pre->next = cur->next ;
newTail->next = cur ;
newTail->next->next = NULL ;
cur = pre->next ;
newTail = newTail->next ;
}
Did i do something wrong?
You need special handling of the case cur == ll->head because in that case prev is not a legal previous element. Also you'll have to update ll->head
Like
if(cur->item % 2 != 0) { // <- Segmentation Fault!
{
if (cur == ll->head)
{
// Add new code here - perhaps something like
ll->head = cur->next;
prev = cur->next;
newTail->next = cur ;
newTail->next->next = NULL ;
cur = ll->head;
}
else
{
// Your current code
}
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 6 years ago.
Improve this question
Lists seem really hard for me. I want to find the smallest element in a file: 1 5 8 6 4 8 6 48 9. It's 1 and I want to delete that 1. I can find the smallest element but can not delete it. I find the smallest element place but not the value. I tried copying deleting function from the web, however I cant understand it due to the fact that I'm really new to C. It writes an error that dereferencing to incomplete type. Please help. Post whole code because it should be more convenient to understand.
#include <stdio.h>
#include <stdlib.h>
typedef struct linkedList {
int value;
struct linkedList *next;
} linkedList, head;
linkedList *readList(linkedList *head) {
FILE *dataFile;
dataFile = fopen("duom.txt", "r");
if (dataFile == NULL) {
printf("Nepasisekė atidaryti failo\n");
} else {
printf("Duomenų failą pavyko atidaryti\n");
}
while (!feof (dataFile))
if (head == NULL) {
head = malloc(sizeof(linkedList));
fscanf(dataFile, "%d", &head->value);
head->next = NULL;
} else {
struct linkedList *current = head;
struct linkedList *temp = malloc(sizeof(linkedList));
while (current->next != NULL) {
current = current->next;
}
fscanf(dataFile, "%d", &temp->value);
current->next = temp;
temp->next = NULL;
}
return head;
}
void search(linkedList *head, int *lowest) {
int a[100];
int i = 0;
int minimum;
int b = 0;
linkedList *current = head;
while (current != NULL) {
a[i] = current->value;
current = current->next;
i++;
}
b = i;
i = 0;
minimum = a[0];
while (b > 0) {
if (minimum > a[i]) {
minimum = a[i];
lowest = i;
}
i++;
b--;
}
}
void deleteNode(struct node **head_ref, int key) {
struct node* temp = *head_ref, *prev;
if (temp != NULL && temp->data == key) {
*head_ref = temp->next; // Changed head
free(temp); // free old head
return;
}
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL)
return;
prev->next = temp->next;
free(temp);
}
void printList(linkedList *head) {
linkedList *current = head;
while (current != NULL) {
printf("%d->", current->value);
current = current->next;
}
printf("NULL\n");
return;
}
int main() {
linkedList *A = NULL;
A = readList(A);
search(A);
head = head->next;
minimum = head->value;
headk->next = head->next;
free(head);
printList(A);
return 0;
}
like this
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct linkedList{
int value;
struct linkedList *next;
} linkedList, node;
linkedList *readList(void){
FILE *dataFile;
dataFile = fopen("duom.txt", "r");
if(dataFile == NULL) {
perror("file open");
return NULL;
}
int v;
node head = {0, NULL}, *curr = &head;
while (1 == fscanf(dataFile, "%d", &v)){
node *new_node = malloc(sizeof(node));
if(new_node == NULL){
perror("malloc");
break;
}
new_node->value = v;
new_node->next = NULL;
curr = curr->next = new_node;
}
fclose(dataFile);
return head.next;
}
int searchMin(linkedList *head){
if(head == NULL){
fprintf(stderr, "%s: The list MUST NOT be NULL.\n", __func__);
return INT_MIN;
}
int min = head->value;
node *p = head->next;
while(p){
if(p->value < min)
min = p->value;
p = p->next;
}
return min;
}
void deleteNode(node **head_ref, int key){
node *curr = *head_ref, *prev = NULL;
while (curr != NULL && curr->value != key){
prev = curr;
curr = curr->next;
}
if (curr == NULL) return;//not found
if(prev)
prev->next = curr->next;
else
*head_ref = curr->next;
free(curr);
}
void printList(linkedList *head){
node *current = head;
while (current != NULL) {
printf("%d->", current->value);
current = current -> next;
}
puts("NULL");
}
void freeList(linkedList *list){
while(list){
node *temp = list;
list = list->next;
free(temp);
}
}
int main(void){
linkedList *A = readList();
int min = searchMin(A);
printList(A);
deleteNode(&A, min);
printList(A);
freeList(A);
return 0;
}
Please try if this program can help you.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct node {
int data;
struct node *next;
};
void push(struct node **head_ref, int new_data) {
struct node *new_node = (struct node *) malloc(sizeof(struct node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void deleteNode(struct node **head_ref, int key) {
struct node *temp = *head_ref, *prev;
if (temp != NULL && temp->data == key) {
*head_ref = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp);
}
void printList(struct node *node) {
while (node != NULL) {
printf(" %d ", node->data);
node = node->next;
}
}
void min(struct node **q) {
struct node *r;
int min = INT_MAX;;
r = *q;
while (r != NULL) {
if (r->data < min) {
min = r->data;
}
r = r->next;
}
printf("The min is %d", min);
deleteNode(q, min);
printf("\n");
}
int main() {
struct node *head = NULL;
FILE *file = fopen("duom.txt", "r");
int i = 0;
fscanf(file, "%d", &i);
while (!feof(file)) {
push(&head, i);
fscanf(file, "%d", &i);
}
fclose(file);
puts("Created Linked List: ");
printList(head);
min(&head);
puts("\nLinked List after Deletion of minimum: ");
printList(head);
return 0;
}
file duom.txt
1 5 8 6 4 8 6 48 9
Test
./a.out
Created Linked List:
9 48 6 8 4 6 8 5 1 The min is 1
Linked List after Deletion of minimum:
9 48 6 8 4 6 8 5 ⏎
I'm busy with implementation of singly linked list and have 2 functions: insert_back and insert_after.
Here is the listing of them:
void insert_back(int data)
{
node *temp1;
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
while (temp1->next != NULL) {
temp1 = temp1->next;
}
node *temp;
temp = (node*)malloc(sizeof(node));
temp->data = data;
temp->next = NULL;
temp1->next = temp;
}
void insert_after(int pos, int data)
{
node *temp1;
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
for (int i = 1; i < pos; i++) {
temp1 = temp1->next;
if (temp1 == NULL) {
return;
}
}
node *temp;
temp = (node*)malloc(sizeof(node));
temp->data = data;
temp->next = temp1->next;
temp1->next = temp;
}
As you can see they are almost the same and for insert back I want to write insert_after(null, 10). I can solve it by adding if condition and choose one of the loops, but it's not my aim.
Is it possible somehow to use one while or for loops together for serial numbers and null?
Also I see that param int pos is int. Should I use 0 instead of null?
You unnecessarily allocate memory in the following lines.
temp1 = (node*)malloc(sizeof(node));
temp1 = head;
This allocated memory will leak as you overwrite the returned address in temp1. You just need temp1 to walk over the list, so there is also no need to allocate any node itself. temp1 can point to any node.
I've taken the liberty to kind of from scratch write a routine doing both things in one go. If pos < 0 it will add the element to the end of the list, otherwise it will add it after the pos-th element, where the first element corresponds with pos == 1. If pos == 0 the element is added at the start of the list.
Also a small main is added to test the routine. new_node has been added to test if memory is not exhausted.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
struct node * next;
int data;
} node;
node * head = NULL;
node * new_node(void)
{
node * result = malloc(sizeof(*result));
if (result == NULL)
{
fprintf(stderr, "Out of memory.\n");
exit(10);
}
return result;
}
void insert_after(int pos, int data)
{
node *walk, * prev;
int i;
prev = NULL;
walk = head;
for (i = 0; walk != NULL && i != pos; i++)
{
prev = walk;
walk = walk->next;
}
if (i != pos && pos > 0)
{
fprintf(stderr, "Location not found.\n");
exit(9);
}
else
{
walk = new_node();
walk->data = data;
if (prev == NULL)
{
walk->next = head;
head = walk;
}
else
{
walk->next = prev->next;
prev->next = walk;
}
}
}
int main(void)
{
int i;
node * wlk;
for (i = 0; i < 10; i++)
{
insert_after(-1, i);
}
for (i = 0; i < 10; i++)
{
insert_after(3, i+10);
}
for (wlk = head; wlk != NULL; wlk = wlk->next)
{
printf("%d\n", wlk->data);
}
return 0;
}
Since you are testing for the end of the chain with insert_after(pos,...) anyway, you could go for:
void insert_after(int pos, int data)
{
node *temp1= head;
for (int i=1; i<pos; i++) {
if (temp1->next==NULL) {
if (pos==INT_MAX)
break; // pos of INT_MAX means insert at end
// so we continue with this last item and append
else
return; // pos higher than length of chain
}
temp1 = temp1->next;
}
...
}
Or slightly more compact:
void insert_after(int pos, int data)
{
node *temp1= head;
for (int i=1; i<pos && temp1->next!=NULL; i++) {
temp1 = temp1->next;
}
if (temp1->next==NULL && pos!=INT_MAX)
return; // pos higher than length of chain, except for
// INT_MAX (for that we just want to continue)
...
}
Then you could use
void insert_back(int data)
{
insert_after(INT_MAX, data);
}