The biggest issue with your current approach surrounds what happens if the first node in the list is part of the sequence and must be removed? When you pass a pointer to sequenza()
by-value, there is no way to change the address of the first node. Instead, simply pass the address of the pointer to sequenza()
which makes compressing sequences in your list trivial. Why approach it this way? See Linus on Understanding Pointers
When you use the address of node to iterate over the list, there is no need to keep track of prev
, current
, or next
values -- there are no special cases. You just check if (node->valero + 1 == node->next->valero)
and if so, add the current value to a temporary sum
and replace the node at the current address with the next node in the list and free the struct that you replaced. If the next node is not in sequence, just add the sum to the current value and continue iterating over your list. One note: before you check the value of node->next->valero
you need to ensure node->next != NULL
.
Putting it altogether, you could do:
/** compress sequences of nodes into a single node */
void sequenza (struct nodo **list)
{
nodo **ppn = list, /* pointer to pointer to head */
*pn = *list; /* pointer to head */
long sum = 0; /* var to hold sum */
while (pn) { /* loop over each node */
/* if next node not null and next value in sequnce */
if (pn->next && pn->valore + 1 == pn->next->valore) {
sum += pn->valore; /* add current to sum */
*ppn = pn->next; /* replace node at current address with next */
free (pn); /* free current node */
pn = *ppn; /* initialize current node pointer */
}
else { /* not in sequnce */
if (sum) { /* if sum not zero */
pn->valore += sum; /* add sum to current value */
sum = 0; /* reset sum zero */
}
ppn = &pn->next; /* get address of next node */
pn = pn->next; /* get pointer to next node */
}
}
}
A full example reading list values from stdin
and calling sequenza()
on the list could be:
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo { /* list node */
int valore;
struct nodo *next;
} nodo;
/** add node at end of list */
nodo *add (nodo **head, int v)
{
nodo **ppn = head, /* pointer to pointer to head */
*pn = *head, /* pointer to head */
*node = malloc (sizeof *node); /* allocate new node */
if (!node) { /* validate allocation */
perror ("malloc-node");
return NULL;
}
node->valore = v; /* initialize members values */
node->next = NULL;
while (pn) {
ppn = &pn->next;
pn = pn->next;
}
return *ppn = node; /* add & return new node */
}
/** compress sequences of nodes into a single node */
void sequenza (struct nodo **list)
{
nodo **ppn = list, /* pointer to pointer to head */
*pn = *list; /* pointer to head */
long sum = 0; /* var to hold sum */
while (pn) { /* loop over each node */
/* if next node not null and next value in sequnce */
if (pn->next && pn->valore + 1 == pn->next->valore) {
sum += pn->valore; /* add current to sum */
*ppn = pn->next; /* replace node at current address with next */
free (pn); /* free current node */
pn = *ppn; /* initialize current node pointer */
}
else { /* not in sequnce */
if (sum) { /* if sum not zero */
pn->valore += sum; /* add sum to current value */
sum = 0; /* reset sum zero */
}
ppn = &pn->next; /* get address of next node */
pn = pn->next; /* get pointer to next node */
}
}
}
/** print all nodes in list */
void prn (nodo *l)
{
if (!l) {
puts ("list-empty");
return;
}
for (nodo *n = l; n; n = n->next)
printf (" %d", n->valore);
putchar ('\n');
}
/** delete all nodes in list */
void del_list (nodo *l)
{
nodo *n = l;
while (n) {
nodo *victim = n;
n = n->next;
free (victim);
}
}
int main (void) {
int v;
nodo *list = NULL;
while (scanf ("%d", &v) == 1)
add (&list, v);
puts ("\noriginal list:");
prn (list);
sequenza (&list);
puts ("\nsequenza sum:");
prn (list);
del_list(list);
}
Example Use/Output
$ echo "10 1 2 3" | ./bin/llsequenza
original list:
10 1 2 3
sequenza sum:
10 6
or
$ echo "10 1 2 3 5 7 8 9 11" | ./bin/llsequenza
original list:
10 1 2 3 5 7 8 9 11
sequenza sum:
10 6 5 24 11
or
$ echo "1 2 3 4 5 6 7 8 9 10" | ./bin/llsequenza
original list:
1 2 3 4 5 6 7 8 9 10
sequenza sum:
55
Look things over and let me know if you have further questions.