Even reverse of a list - c

The problem is taking a linked list and reversing the even nodes only. That is, a list 1->2->3->8 should become 1->8->3->2.
The solution I came up with traverses the list one and is constant in space. I believe that the problem has to be with copying the values of each node, rather than changing the pointers. They seem just not to be copied.
Here is the first version,
listnode * solve(listnode* A) {
if(A == NULL || A->next == NULL)
return A;
listnode * current = A, * prev = NULL;
size_t dim = 0;
int nextVal, hasPrevious = 0;
while(current != NULL) {
dim++;
if(dim % 2 == 0 && !hasPrevious) {
prev = current; //We store the previous value
hasPrevious = 1; //We now have a previous value
}
if(hasPrevious && dim % 2 == 0) {
nextVal = current->val; //I store the value to plug it into previous
current->val = prev->val; //Here I update next value with the previous value.
prev->val = nextVal; //And now previous value has nextValue
hasPrevious = 0; //We no longer have a previous value to copy
}
current = current->next;
}
return A;
}
The second solution is the same but using the -> operator when copying the values, but same result.
listnode * solve(listnode* A) {
if(A == NULL || A->next == NULL)
return A;
listnode * current = A, * prev = NULL;
size_t dim = 0;
int nextVal, hasPrevious = 0;
while(current != NULL) {
dim++;
//I work from the odd nodes such that I access the
//other nodes deferencing the pointer, and thus
//changing the content of the node.
if(dim % 2 == 1 && !hasPrevious) {
prev = current; //We store the previous value
hasPrevious = 1; //We now have a previous value
}
if(hasPrevious && dim % 2 == 1) {
nextVal = current->next->val; //I store the value to plug it into previous
current->next->val = prev->next->val; //Here I update next value with the previous value.
prev->next->val = nextVal; //And now previous value has nextValue
hasPrevious = 0; //We no longer have a previous value to copy
}
current = current->next;
}
return A;
}
T

Assuming a -> b -> c -> d -> e -> f -> g -> h -> i -> j should become a -> j -> c -> h -> e -> f -> g -> d -> i -> b, (i.e. put all the nodes at even positions (counting from 1) in reverse order), I do not believe that can be done in a single pass through the list, at least for a singly linked list. It can be done in two passes.
The way I would implement it is as follows:
Extract the even nodes onto a new list.
Reverse the order of the nodes of the new list.
Merge the new list back into the original list.
Since it is easy to construct a list in reverse order from single nodes, steps 1 and 2 can be combined into a single step. So the two passes are:
Extract the even nodes onto a new list in reverse order.
Merge the new list back into the original list.
This solution reorders the list nodes by pointer manipulation rather than by swapping the values contained within nodes. I think this is what is normally expected when solving linked list problems.
Example implementation:
#include <stddef.h>
#include "listnode.h"
listnode *solve(listnode *A) {
listnode *rev;
listnode *el;
listnode *ne;
/*
* First pass.
*
* Loop through pairs of nodes (el and ne) moving the second node
* of each pair to a new list (rev) in reverse order.
*/
rev = NULL;
el = A;
while (el != NULL && (ne = el->next) != NULL) {
el->next = ne->next;
el = ne->next;
ne->next = rev;
rev = ne;
}
/*
* Second pass.
*
* Merge the reversed list of nodes (second node of each pair in reverse
* order) back into the original list.
*/
el = A;
while (rev != NULL) {
ne = rev;
rev = ne->next;
ne->next = el->next;
el->next = ne;
el = ne->next;
}
/* Return start of reordered list. */
return A;
}

Related

Combine like Polynomial Terms in stored in a linked list

I have a link list that each node stores the next node and the term. The term stores the coefficient, variable, and exponent. I need to iterate through the list and combine all like terms returning the first node with all others attached to it. I'm not even 100% sure if I am starting in the right place.
node_t * combine_like_terms(const node_t * current_node_ptr) {
if(current_node_ptr == NULL){
return NULL;
}
// node_t * start_node = current_node_ptr;
const node_t * curr = current_node_ptr;
node_t * newnodelist = NULL;
int maxexponent = 0;
do{
term_t *t = curr->term;
if(curr->term->exponent > maxexponent)
{
maxexponent = t->exponent;
}
}while((curr = curr->next_node));
puts("Max exp: \n");
curr = current_node_ptr;
for(int i = 0; i <= maxexponent; i++){
int coefficient = 0;
do{
term_t *x = curr->term;
if(x->exponent == i){
coefficient += x->coefficient;
}
}while((curr = curr->next_node));
term_t * terms = malloc(sizeof(term_t));
terms->coefficient = coefficient;
terms->var = 'x';
terms->exponent = i;
add_node(&newnodelist,terms);
}
return newnodelist;
}
due to some circumstances outside of my control the method return type and arguments can't be changed. My current idea is to find the highest exponent, then to go back through and find all coefficients with of each individual exponent and add them then add those new terms to a list. I am getting a segmentation fault before the puts("Max Exp: \n"); that I do not know that cause of.

intersection of linked lists

Output showing the wrong intersection of List 1 and List 2I am writing a function for the intersection of two linked lists but somehow I keep getting the wrong output.The idea is to initialize an empty list and to traverse through list 1 by using Find function to check if it intersects with list 2.If it does, then it is added to the list 4 (answer) which is returned after traversing through the list 1.
Here is the function, as well as the supporting functions it calls:
List Intersection(List L1, List L2) {
List L4 = MakeEmpty(NULL);
Position A = First(L1);
Position B = First(L2);
Position C = Header(L4);
while(A != NULL){
if(Find(A->Element, L2) != NULL) {
Insert(A->Element, L4, C);
A = A->Next;
C = C->Next;
} else {
A = A->Next;
}
}
return L4;
}
Position Find( ElementType X, List L ) {
Position P = L->Next;
while( P != NULL && P->Element != X )
P = P->Next;
return P;
}
void Insert( ElementType X, List L, Position P ) {
Position TmpCell = malloc( sizeof( struct Node ) );
// [check for null]
TmpCell->Element = X;
TmpCell->Next = P->Next;
P->Next = TmpCell;
}

Deleting Consecutive Element in a Linked List

Given the following definition of linked-list
typedef struct elemento {
int inf;
struct elemento *next;
} lista;
I'm trying to create a function
lista *SeekAndDestroy(lista *p, int k);
that, given a list *p and a positive integer k, which searches on the list, the first sequence of consecutive elements whose sum is exactly k and eliminate such elements from the list.
My try:
lista *SeekAndDestroy(lista *p, int k) {
lista *a, *nuovo;
int x = 0;
a = (lista *)malloc(sizeof(lista));
a->inf = p->inf;
nuovo = a;
p = p->next;
while (p != NULL) {
if (p->next != NULL) {
if ((p->inf + p->next->inf) == k) {
if (x != 1) {
p = p->next->next;
x = 1;
continue;
}
}
}
nuovo->next = (lista *)malloc(sizeof(lista));
nuovo = nuovo->next;
nuovo->inf = p->inf;
p = p->next;
}
nuovo->next = NULL;
return a;
}
This my solution has two main problems:
1) erases a maximum of two consecutive elements and not more
2) if the items to be deleted are the first two, the function does not work
How can i solve this problem? Thanks
For now, let's forget about linked list and pointer and stuffs. Say, we have to solve the problem for a given array. Can we do that? Sure!
for (int i = 0; i < array.length; ++i) {
for (int j = i; j < array.length; ++j) {
int sum = getRangeSum(array, i, j);
if (sum != k) continue;
// construct new array and return
}
}
This code can be optimized further but let's keep it simple for now. So, in linked list, similar approach can be used. And the delete part is also simple. You can keep a variable to keep track of the previous node of i. Let's call it iParent. Now, we can remove the [i, j] segment as iParent->next = j->next.
Obviously, you need to consider some corner cases like if such segment is not found or if the segment starts from the beginning of the linked list etc.
Here's a function I wrote to tackle the two problems faced by you and any other boundary conditions:
list* Seek_Destroy(list* head, int target){
if(head == NULL)
return NULL;
list* temp = head;
bool find_complete = false;
list *prev = temp;
//Loop for iterating until list is complete or target sum is found.
while( !find_complete){
//Create a pointer for loop calculations
list* sum_loop = temp;
//Initialize sum to 0
int sum =0;
//Loop for checking whether the sum is equal to the target
while(sum <= target && sum_loop->next!= NULL){
//Keep adding the sum
sum += sum_loop->inf;
if(sum == target){
//Set the flag for exiting outer loop
find_complete = true;
//Test whether head of the list is included in the sum
if (temp == head){
//Make head point to the struct after the last element included in the sum loop
head = sum_loop->next;
//Delete and free memory
while(temp!= sum_loop){
list* del = temp;
temp = temp->next;
free(del);
}
}else {
//Set the next pointer of previous element of the list to point after the last element included in the sum loop
prev->next= sum_loop->next;
//Delete and free memory
while(temp!= sum_loop){
list* del = temp;
temp = temp->next;
free(del);
}
}
break;
}
//Increment the pointer for the sum calculation
sum_loop = sum_loop->next;
}
prev = temp;
//Make temp point to next element in the list
temp = temp->next;
//IF entire list is traversed set the flag to true
if (temp ==NULL){
find_complete = true;
}
}
return head;
}
Assuming your numbers are all non-negative, there's a more efficient algorithm you can use. You simply run two pointers, ptrA and ptrB, through the list, maintaining the sum of the inclusive elements.
If the sum isn't what you need, you do one of two things. First, if your current sum is less than that needed, bring the next element into the array by advancing ptrB.
If your current sum is more than what you need, you take out the first element in your range by advancing ptrA. Both these operations should, of course, adjust the current range sum. There's an edge case here in that you don't want to do this if there's currently only one item in the range.
And it should go without saying that, if the current range sum is equal to what you need, you simply delete that range and exit.
In terms of pseudo-code, it would be something like:
def delExact(list, desiredSum):
# Check non-empty and start range.
if list is empty:
return
ptrA = list.first
ptrB = ptrA
rangeSum = ptrA.value
# Continue until match found
while rangeSum is not equal to desiredSum:
# Select add-another or remove-first.
if ptrA == ptrB, or rangeSum < desiredSum:
# Need to bring another in, returning if list exhausted.
ptrB = ptrB.next
if ptrB == null:
return
rangeSum = rangeSum + ptrB.value
else:
# Need to remove one.
rangeSum = rangeSum - ptrA.value
ptrA = ptrA.next
# If we exit the loop, we've found a sum match.
# Hence we need to delete ptrA through ptrB inclusive.
However, that two-pointer approach breaks down if negative numbers are allowed since you don't actually know what effect later elements may have.
In that case, you basically have to do an exhaustive search of all possibilities, and that basically boils down to:
for each element in list:
for each possible segment from that element on:
check and act on summed data
That's actually more of an English representation, the pseudo-code for such a beast would be along the lines of:
def delExact(list, desiredSum):
# For each list element.
ptrA = list.first
while ptrA is not null:
# For each possible segment starting at that element.
segmentSum = 0
ptrB = ptrA
while ptrB is not null:
add ptrB.value to segmentSum
# Delete segment if sum matches, then return.
if segmentSum is equal to desiredSum:
# Here we delete from ptrA through ptrB inclusive.
return
# Otherwise, keep adding elements to segment.
ptrB = ptrB.next
# No matching segment, move on to next element.
ptrA = ptrA.next
# No matching segment at any element, just return.
The use of either of those algorithms will solve your problem regarding only deleting two elements.
The problem of deleting at the start of the list is to simply recognise that fact (ptrA == list.first) and make sure you adjust the first pointer in that case. This is a standard edge case in linked list processing, and can be implemented as something like:
def deleteRangeInclusive(list, ptrA, ptrB):
# Adjust list to remove ptrA/ptrB segment,
# allowing for possibility ptrA may be the head.
if ptrA == list.first:
list.first = ptrB.next
else:
beforeA = list.first
while beforeA.next != ptrA:
beforeA = beforeA.next
beforeA.next = ptrB.next
# Now we can safely remove the ptrA-ptrB segment.
while ptrA != ptrB:
tempA = ptrA
ptrA = ptrA.next
delete element tempA
delete element ptrB
I solved like that:
Lista *Distruggi(Lista *p, int k) {
Lista *n = NULL, *nuova = NULL;
int z = 0;
for (Lista *i = p; i != NULL && z != 1; i = i->next) {
for (Lista *j = i; j != NULL; j = j->next) {
int sum = somma(i, j);
if (sum != k) continue;
n = (Lista *)malloc(sizeof(Lista));
n->inf = p->inf;
p = p->next;
nuova = n;
while (p != i) {
nuova->next = (Lista *)malloc(sizeof(Lista));
nuova = nuova->next;
nuova->inf = p->inf;
p = p->next;
}
while (j != NULL) {
nuova->next = (Lista *)malloc(sizeof(Lista));
nuova = nuova->next;
nuova->inf = j->inf;
j = j->next;
}
z = 1;
break;
}
}
if (z == 0) return p;//NO CHANGE
else {//CHANGE
nuova->next = NULL;
return n;
}
}

C Bubblesort in LinkedList

I'm trying to sort a doubly linked list, but I'm having some trouble. I'm a noob in C and I guess my problem is with pointers..
I just can't see how to swap two positions inside the list and so maybe that's the issue.
I tryied to sort it by using Bubblesort, even knowing that it's complexity is not so good because, how I'm still learning, thought that it was an easy way to start.
I also tryied reading some things about swaping elements in a linkedlist and how to sort them, but I'm really stuck with this problem...
PS: I started the for with the m->next cause my list has a header(m).
PS2:I'm getting the error "request for member ‘next’ in something not a structure or union", and don't know how to fix it
struct segment {
int x, y; /// position
char c; // letter
struct segment* next;
struct segment* prev;
};
void sortingSegments(struct segment* m) {
struct segment **j; struct segment **i;
for(i = &((m->next)->next); i !=NULL; i = i->next) {
for(j = &(m->next); j == i; j = j->next) {
if ((*j)->c > (*i)->c) {
struct segment **aux;
aux = i;
(*aux)->next = (*i)->next;
(*aux)->prev = (*i)->prev;
i = j;
(*i)->next = (*j)->next;
(*i)->prev = (*j)->prev;
j = aux;
(*j)->prev = (*aux)->prev;
(*j)->next = (*aux)->next;
}
}
}
}
Please read the comments and try to understand the linking of nodes.
It is based on the simple bubble sort described in wikipedia.
void sortingSegments(struct segment** m) {
struct segment *i, *tmp, *prev, *next;
int swapped = 1;
/*
* https://en.wikipedia.org/wiki/Bubble_sort#Pseudocode_implementation
* n = length(A)
* repeat
* swapped = false
* for i = 1 to n-1 inclusive do
* //if this pair is out of order
* if A[i - 1] > A[i] then
* // swap them and remember something changed
* swap(A[i - 1], A[i])
* swapped = true
* end if
* end for
* until not swapped
*/
// looping until no more swaps left
while (swapped) {
swapped = 0;
// we begin from the second item at each iteration
for (i = (*m)->next; i; i = i->next) {
// we need to swap i with i->prev
if (i->prev->c > i->c) {
prev = i->prev;
next = i->next;
// swapping first and second elements,
// so update m to reflect the change made
// to the head of the list
if (prev == *m) {
*m = i;
}
// so there is a prev of prev, update that two links
else {
prev->prev->next = i;
i->prev = prev->prev;
}
// so there is a next, update that two links
if (next) {
next->prev = prev;
prev->next = next;
}
// no next element, mark the end of the list
else {
prev->next = NULL;
}
// this is obvious, prev now becomes i's next
prev->prev = i;
i->next = prev;
// this is needed to reflect the change in i
i = prev;
swapped = 1;
}
}
}
}

a c program to add two singly linked lists, of unequal lengths containing single digited numbers in all of their nodes

i got this as an interview question. i was given 2 linked lists of unequal lengths,containing a single digited number in each of their nodes. i was asked to build a 3rd linked list which contains the sum of the two linked lists, again in the form of 1 digit in a node.
ex:
linked list 1 is
4-7-9-6
linked list 2 is
5-7
then the 3rd linked list would be
4-8-5-3
can someone suggest me an efficient algorithm, with minimum compromise in terms of space complexity?(i am not expecting an algo dat involves reversing the lists many times).
Reverse lists 1 and 2
Sum element-by-element (while
maintaining a carry), putting the
results in a list 3 that you
construct from tail to head
OR
Convert lists 1 and 2 to ints (e.g. int list1AsInt = 0; For each node {list1AsInt *= 10; list1AsInt += valueOfThisNode;} )
Sum those ints
Convert the result to a linked list (e.g. valueOfBrandNewNode = list3AsInt % 10; list3AsInt /= 10; Add a new node that points to the prev one; )
OR
Traverse both lists once to find out
their lengths. For this example,
let's assume that list 1 is longer
by N nodes.
Create a list 3 to represent the sum
without carries and a list 4 to
represent the carries.
For the first N nodes of list 1,
copy those values to list 3 and make
list 4's values be 0.
For the remaining nodes of lists 1
and 2, sum element-by-element,
putting the sum mod 10 in list 3 and
the carry in list 4. Keep track via
a bool of whether list 4 is all 0's.
Add a last node with value 0 to list
4.
If list 4 is entirely 0's, done.
Else, recurse to step 2,
treating list 3 as
the new list 1 and list 4 as the new
list 2. We know the length of the
new list 1 is the larger of the lengths
of the old lists 1 and 2, and the length
of the new list 2 is one more than that.
Read each digit as its ASCII equivalent into a char array indexed from 0, for both lists.
Use the atoi() function on both char arrays ( you may use atol() or atoll() if you are concerned about the length)
Add both numbers
Use the itoa() function to convert to a char array & then put back into new list.
Although, I admit the itoa() function is not standard.
If the lists are doubly linked it's easy:
Traverse both lists to the end.
Add the digits in corresponding nodes, and keep the carry digit.
Create the node in list 3.
Move one node towards the start of the lists and repeat.
The solution could be much simpler if the list stored the numbers in reverse order.
Nevertheless, with the given constraint, here is an approach.
find the nthToLast digit of both lists, starting with n = 0,
create a node with the sum of the digits,
update the (running) carry,
insert the newly created node at the head of the result list
Following is the (untested) C code.
typedef struct DigitNode_ {
int digit;
struct DigitNode_ * next;
} DigitNode;
/* Returns the n-th element from the end of the SLL;
if no such element exists, then return NULL.
See: https://stackoverflow.com/questions/2598348/
*/
extern DigitNode * nthNodeFromTail( DigitNode * listHead, size_t n );
/* Push pNode in the front, i.e. as the new head of the list */
extern void pushFront( DigitNode ** pListHead, DigitNode * pNode );
/* Create new list as sum of a and b, and return the head of the new list.
a -> 4 -> 7 -> 9 -> 6 -> NULL
b -> 5 -> 7 -> NULL
results in
c -> 4 -> 8 -> 5 -> 3 -> NULL
*/
DigitNode * sumDigitLists( DigitNode * a, DigitNode * b ) {
DigitNode * c = 0;
int carry = 0;
/* i is the position of a node from the tail of the list, backwards */
for( size_t i = 0; /* see 'break' inside */; i++ ) {
const DigitNode * const ithNodeA = nthNodeFromTail( a, i );
const DigitNode * const ithNodeB = nthNodeFromTail( b, i );
/* Stop when processing of both lists are finished */
if( !ithNodeA && !ithNodeB ) {
break;
}
const int ithDigitA = ithNodeA ? ithNodeA->digit : 0;
const int ithDigitB = ithNodeB ? ithNodeB->digit : 0;
assert( (0 <= ithDigitA) && (ithDigitA <= 9) );
assert( (0 <= ithDigitB) && (ithDigitB <= 9) );
const int conceptualIthDigitC = carry + ithDigitA + ithDigitB;
const int ithDigitC = conceptualIthDigitC % 10;
carry = conceptualIthDigitC / 10;
DigitNode ithNodeC = { ithDigitC, NULL };
pushFront( &c, &ithNodeC );
}
return c;
}
Take a look at this code:
node *add_two_linkedlist(node *head1,node *head2)
{
int i,j,temp;
node *p,*n;
p=head1;
n=head2;
i=count(head1);
j=count(head2);
if(i>j)
{
while(j!=0)
{
p->data=p->data+n->data;
if(p->data>10)
{
temp=(p->data)/10;
p->data=(p->data)%10;
p=p->next;
n=n->next;
p=p->data+temp;
j--;
}
}
return head1;
}
if(j>i)
{
while(i!=0)
{
n->data=p->data+n->data;
if(n->data>10)
{
temp=(n->data)/10;
n->data=(n->data)%10;
n=n->next;
p=p->next;
n=n->data+temp;
i--;
}
}
return head2;
}
}
This is straightforward. Assuming the leftmost node is the most significant bit. Align the two lists, add and propagate carry. Upon return create a new node if required..
#include <stdio.h>
struct list {
int val;
struct list * next;
};
int listadd (struct list *l1, struct list *l2) {
if ((l1 == NULL) || (l2 == NULL))
return;
int carry = 0;
if ((l1->next == NULL) && (l2->next != NULL)) {
carry += listadd (l1, l2->next) + l2->val;
return carry;
}
else if ((l1->next != NULL) && (l2->next == NULL)) {
carry +=listadd (l1->next, l2);
l1->val = l1->val + carry;
}
else if ((l1->next != NULL) && (l2->next != NULL)) {
carry += listadd (l1->next, l2->next);
}
else if ((l1->next == NULL) && (l2->next == NULL)) {
l1->val = l1->val + l2->val;
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
struct list * createnode (int val) {
struct list * temp = (struct list *) malloc (sizeof(struct list));
temp->val = val;
temp->next = NULL;
return temp;
}
int main() {
int carry = 0;
struct list *l1 = createnode(1);
l1->next = createnode(2);
struct list *l2 = createnode(7);
l2->next = createnode(8);
carry = listadd(l1,l2);
if (carry != 0) {
struct list * temp = createnode(carry);
temp->next = l1;
l1 = temp;
}
while (l1!= NULL) {
printf ("%d", l1->val);
l1=l1->next;
}
}

Resources