My task is to generate random numbers in range from 50 to 80, if generated number is even add it to list of even numbers, if it is odd add it to list of odd numbers. Program should run till both lists are filled with 10 numbers. Duplicates in list are not allowed. This code prints 20 different numbers and it is storing duplicates in list. So I think problem is with count_odd, count_even and checking for duplicates but I can’t find solution to that. Also I have to print all generated numbers and also both lists in the end. Numbers in linked list should be in descending order
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
typedef struct list numbers;
typedef struct list* Pos;
int PrintRandom();
Pos CreateNew();
int PrintList(Pos);
struct list {
int number;
Pos next;
};
int PrintList(Pos P) {
if (P == NULL)
printf("Empty list.\n");
while (P != NULL) {
printf("%d\n", P->number);
P = P->next;
}
return 0;
}
Pos CreateNew() {
Pos q = NULL;
q = (Pos)malloc(sizeof(struct list));
if (q == NULL) return NULL;
q->next = NULL;
return q;
}
int PrintRandom() {
int x = 0, max = 80, min = 50;
x = (rand() % (max - min + 1) + min);
printf("Random number is : %d\n", x);
return x;
}
int main() {
srand(time(0));
Pos even, odd, q = NULL;
even = malloc(sizeof(numbers));
odd = malloc(sizeof(numbers));
even->next = odd->next = NULL;
int count_even = 0, count_odd = 0, j;
Pos head_p =even, head_n=odd;
while (count_even < 10 & count_odd < 10) {
j = PrintRandom();
if (j % 2 == 0) {
q = CreateNew();
if (q == NULL) return -1;
q->number = j;
while (even->next != NULL && even->next->number > q->number) {
even = even->next;
}
if (even->number== q->number)
free(q);
else
q->next = even->next;
even->next = q;
even =head_p;
count_even++;
}
else {
q = CreateNew();
if (q == NULL) return -1;
q->number = j;
while (odd->next != NULL && odd->next->number > q->number) {
odd = odd->next;
}
if (odd->number == q->number)
free(q);
else
q->next = odd->next;
odd->next = q;
odd = head_n;
count_odd++;
}
}
printf("Even numbers in list are:\n");
PrintList(head_p->next);
printf("Odd numbers in list are:n");
PrintList(head_n->next);
return 0;
}
Your code has several bugs:
First bug:
The loop
while (count_even < 10 & count_odd < 10) {
will stop as soon as either count_even or count_odd reaches 10. However, in your question, you stated that the loop should only stop when both have reached 10.
Therefore, you should change that line to the following:
while ( count_even < 10 || count_odd < 10 ) {
Also, it is worth pointing out that & is the bitwise-AND operator. You probably intended to use the logical-AND operator, which is &&.
Second bug:
In the comments section, you stated that if one of the lists is already full (has 10 elements), then all additional numbers that belong in that list should be discarded instead. However, your program does not contain any code to check for this. Instead, your program will keep adding new elements to the list, even if it already has 10 elements.
Third bug:
The following code is wrong:
if (even->number== q->number)
free(q);
else
q->next = even->next;
even->next = q;
even =head_p;
count_even++;
First of all, you should change the expression
even->number== q->number
to:
even->next->number== q->number
However, since even->next may be null, you must test for that beforehand, so that the entire line would look like this:
if ( even->next != NULL && even->next->number== q->number)
Also, the lines
even->next = q;
and
count_even++;
should not be executed if the number already exists. Therefore, you should move these lines inside the else block. After performing these changes, your code should look like this:
if ( even->next != NULL && even->next->number== q->number)
{
free(q);
}
else
{
q->next = even->next;
even->next = q;
count_even++;
}
even =head_p;
The same changes should be performed on the code branch for the odd numbers.
Fourth Bug:
There is a backslash character missing in the following line:
printf("Odd numbers in list are:n");
You should change it to:
printf("Odd numbers in list are:\n");
Additional remarks:
There are two other things that I think could be improved in your code:
The first element of the linked list is just a dummy node in which the number field is not initialized. You seem to be using this node for nothing else than holding the head pointer to the actual linked list.
You have a lot of code duplication. Instead of using the same code for handling both even and odd numbers, you have separate, but very similar code for handling each case.
In the code below, I have rewritten most of your code to show you can see how I would solve this problem. Don't be surprised if you find it hard to understand, as I am using pointers to pointers, which can be hard for beginners to understand. As you can see, I am not using any dummy nodes, and I am also using the same code for handling both even and odd numbers. Only in two places of my code do I have different code for handling even and odd numbers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
struct list_node
{
int number;
struct list_node *next;
};
int PrintRandom();
int PrintList( struct list_node * );
int PrintList( struct list_node *p)
{
if ( p == NULL )
{
printf( "Empty list.\n" );
}
else
{
while ( p != NULL )
{
printf( "%d\n", p->number );
p = p->next;
}
}
return 0;
}
int PrintRandom() {
int x = 0, max = 80, min = 50;
x = (rand() % (max - min + 1) + min);
printf("Random number is : %d\n", x);
return x;
}
int main()
{
srand( (unsigned)time(NULL) );
struct list_node *head_even = NULL, *head_odd = NULL;
int count_even = 0, count_odd = 0, random;
bool is_even;
while ( count_even < 10 || count_odd < 10 )
{
struct list_node **pp, *p, *q;
//generate and print random number
random = PrintRandom();
//determine whether number is even or odd
is_even = random % 2 == 0;
//set pp to point to head pointer of the appropriate list
//and check whether the appropriate list is already full
if ( is_even )
{
if ( count_even >= 10 )
continue;
pp = &head_even;
}
else
{
if ( count_odd >= 10 )
continue;
pp = &head_odd;
}
for (;;) //infinite loop, equivalent to while (1)
{
p = *pp;
//if we reached the end of the list, break out of the loop
if ( p == NULL )
break;
if ( p->number <= random )
{
if ( p->number == random )
{
//discard number, because it already exists in list
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto next_outer_loop_iteration;
}
else
{
break;
}
}
pp = &p->next;
}
//allocate memory for new node
q = malloc( sizeof *q );
if ( q == NULL)
{
fprintf( stderr, "error allocating memory for new node!\n" );
exit( EXIT_FAILURE );
}
//initialize new node
q->number = random;
q->next = p;
//insert node into list
*pp = q;
//increment the appropriate counter
if ( is_even )
count_even++;
else
count_odd++;
next_outer_loop_iteration:
continue;
}
printf("Even numbers in list are:\n");
PrintList( head_even );
printf("Odd numbers in list are:\n");
PrintList( head_odd );
//NOTE: The memory of the linked lists is not being freed
return 0;
}
Related
I have to make my lab))
In general, I should find the index of three students with the smallest rating points.
How I can do it without three loops? Just by one.
In this function, I use structures and output arguments.
int addDelateThree(stud** pListHead, int* Imin, int* Jmin, int* Cmin) {
stud* pTemp = pListHead;
stud* SpTemp = pListHead;
stud* TpTemp = pListHead;
int check = 0;
double min1 = pTemp->madian;
double min2 = SpTemp->madian;
double min3 = pTemp->median;
int i = 0;
while (pTemp != NULL) {
if (min1 > pTemp->madian) {
min1 = pTemp->madian;
*Imin = i;
}
i++;
pTemp = pTemp->next;
}
i = 0;
while (SpTemp != NULL) {
if (min2 > SpTemp->madian && i != *Imin) {
min2 = SpTemp->madian;
*Jmin = i;
}
i++;
SpTemp = SpTemp->next;
}
i = 0;
while (TpTemp != NULL) {
if (min3 > TpTemp->madian && i != *Imin && i != *Jmin) {
min3 = TpTemp->madian;
*Cmin = i;
}
i++;
TpTemp = TpTemp->next;
}
}
Make a list of 3 stud *. Initialize all to point to a dummy record whose .madian = INFINTY;
Walk the linked list once.
Compare node's .madian to list[2]->madian. If <=, adjust list of 3 with new minimal .madian. This may involve several compares as code compares 1st the greatest min value, then next greatest min and finally the least value.
Report result.
O(n) solution.
I am writing a recursive function to find if there is a path from the root to a leaf that sums up to a certain number or not (user inputs the sum). Each time I move forward into a new recursive call, I increment the value of current_sum with the value of node->data. Current_sum is declared/initialized outside of the function. So this works fine to get the sum to the left-ermost leaf. However after that, the current_sum just keeps increasing, as I don't have an appropriate decrement operation to go with it. So if there does exist a path that adds up to a certain number in the righter branches, for example: 1 2 # # 3 # #, and I check for path sum = 4, (1+3), it would not get that. (If i check for sum=3 (1+2), it does get it.)
So I am looking for the correct place in my code to put the decrement operation. I was thinking something like: current_sum -= root->data. However I've tried putting it a lot of different places, but all of them seem to be wrong places. Either they disrupt the original tracker to get to even the very first leftermost leaf. Or they don't decrement at all (if I put it after the both the left/right recursive calls). I also do need it to keep decrementing while it goes UP but increment while it goes DOWN. Is there a way to write this in code, I am curious? Or, is this just a bad algorithm/approach?
I've seen other ways of solving this problem, such as https://www.geeksforgeeks.org/root-to-leaf-path-sum-equal-to-a-given-number/, which seem really nice, I just wanted to know if there was a way to resolve the one I started.
int current_sum = 0;
int sumPath(Node * root, int sum)
{
if (root == NULL)
{
return 0;
}
current_sum += root->data;
if ((root->left == NULL) && (root->right == NULL))
{
if (current_sum == sum)
{
return 1;
}
else
{
return 0;
}
}
int the_left = sumPath(root->left, sum);
int the_right = sumPath(root->right, sum);
////////////////////current_sum -= root->data; (?)
if (the_left>0)
{
return the_left;
}
else if (the_right>0)
{
return the_right;
}
return 0;
}
You may get invalid output, because of not sending current_sum as a parameter. Because current_sum needs to be updated for a particular stack-trace or function call, not for commonly for all the function calls. and this may give you an invalid state.
UPDATE
int isPossible(Node * root, int currentSum, int sum) {
if(!root) return 0;
currentSum += root.node;
// when you find the sum, and can't move further down
if(sum == currentSum && root->left == null && root->right == null) return 1;
int flag = 0;
// going down on left side
flag = isPossible(root->left, currentSum, sum);
// needs to check right side, only when you couldn't find sum on left
if(!flag)
flag = isPossible(root->right, currentSum, sum);
// return the state
return flag;
}
your code is fine, u just need to pass sum - current_sum in the recursive call. This is your code with some hinted modifications.
#include <stdio.h>
// remove global current_sum
struct Node {
char* name;
int data;
struct Node* left;
struct Node* right;
};
int sumPath(struct Node* root, int sum) {
if (root == NULL) {
return 0;
}
if ((root->left == NULL) && (root->right == NULL)) {
if (current_sum == sum) {
printf("%s ", root->name); // if the branch matches, print name
return 1;
} else {
return 0;
}
}
int the_left = sumPath(root->left, sum - root->data); // pass the subtracted sum
int the_right = sumPath(root->right, sum - root->data); // pass the subtracted sum
if (the_left > 0) {
printf("%s ", root->name); // if the branch matches, print name
return the_left;
} else if (the_right > 0) {
printf("%s ", root->name); // if the branch matches, print name
return the_right;
}
return 0;
}
int main() {
struct Node n1 = {.data = 1, .name = "n1"}; // n1
struct Node n2 = {.data = 1, .name = "n2"}; // ___|___
struct Node n3 = {.data = 1, .name = "n3"}; // | |
struct Node n4 = {.data = 1, .name = "n4"}; // n2 n4
// ___|
n1.left = &n2; // |
n1.right = &n4; // n3
n2.left = &n3; //
sumPath(&n1, 3); // no. of steps including the root
return 0;
}
// output
// n3 n2 n1
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;
}
}
I'm new in programming. At current learning C language.I'm confused right now in a problem which is showing unexpected result after running.
The problem is-
I want to make a program which take input one more than when the user input 42 and stop taking input after it and print all the numbers user had typed before 42 has come.
For example-Input:
1
2
88
42
99
Output:
1
2
88
My Program-
#include <stdio.h>
int main()
{
int i = 1, j, temp;
printf("enter numbers:\n");
while (i)
{
scanf("%d", &temp);
i++;
int a[i];
a[i - 2] = temp;
if (temp == 42)
{
scanf("%d", &a[i - 1]);
for (j = 0 ; j < i - 1 ; j++)
{
if (a[j] == 42)
break;
else
printf("%d\n",a[j]);
}
}
if (temp == 42)
break;
}
return 0;
}
When i input the same value as in example i get unexpected result such as-
4196363
0
-1
Please help.And sorry for my bad english.Thankyou in advance.
You are printing uninitialized values because if i's value becomes 3 and greater values after that you never set a[0] as well as all the values before a[i - 2].
Thus causing Undefined Behavior at the following line
printf("%d\n", a[j]);
some values are uninitialized and you still try to print them.
You should notice that a is being redeclared at each iteration and you are not initializing the values because the values in the previous a where only valid in the previous iteration.
The a variable is valid only within the scope of the while loop but not only because it's not declared outside, also because it's deallocated when it becomes out of scope. Perhaps an example will make it clearer.
Suppose you had the following program
int main(void)
{
int *pointer = NULL;
if (pointer == NULL)
{
int array[5] = {1, 2, 3, 4, 5};
pointer = array;
}
/* `poitner' points to `array` but array was deallocated */
for (int i = 0 ; i < 5 ; ++i)
printf("%d\n", pointer[i]); /* This is UB */
return 0;
}
this would compile, however as you can see it will invokes undefined behavior.
Since it's not possible to understand what your code does, I suggest the following
#include <stdio.h>
int main()
{
int i = 1;
int a[100];
printf("enter numbers:\n");
while (i++ < 100)
{
if (scanf("%d%*c", &a[i - 2]) != 1)
return -1; /* this was invalid input, it will cause UB */
if (a[i - 2] == 42)
{
if (scanf("%d%*c", &a[i - 1]) != 1)
return -1; /* this was invalid input, it will cause UB */
for (int j = 0 ; j < i - 1 ; j++)
{
if (a[j] == 42)
break;
else
printf("%d\n", a[j]);
}
}
if (a[i - 2] == 42)
break;
}
return 0;
}
This at least removes undefiend behavior and meakes teh code more readable, but it's still not clear what is this program for or what it should do.
In general case because the number of entered values is unknown you need to allocate dynamically storage for a new entered value.
So I would build a list that contains entered values. The other approach as to use malloc and realloc for the whole array when a new value is entered. In my opinion it is a worse solution than to build a list.
The program can look the following way
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
struct node
{
int value;
struct node *next;
} * head = NULL;
struct node **current = &head;
int value;
int next = -1;
while ( next != 1 && scanf( "%d", &value ) == 1 )
{
if ( next == 0 || value == 42 ) ++next;
if ( next == -1 )
{
*current = malloc( sizeof( struct node ) );
( *current )->value = value;
( *current )->next = NULL;
current = &( *current )->next;
}
}
while ( head )
{
printf( "%d\n", head->value );
struct node *tmp = head;
head = head->next;
free( tmp );
}
}
If to enter for example the following values
1 2 3 4 5 6 7 8 9 42 10
then the program output will be
1
2
3
4
5
6
7
8
9
The list stores neither 42 nor the next value after 42 though you can modify the program such a way that it would store also these values.
As for your code then at least this statement
a[i - 2] = temp;
is wrong when i is equal to 1 and results in undefined behaviour of the program.
And I do not see that i would be changed.
I think your problem is trying to declare(and redeclare) a[i] multiple times with different values. The compiler needs to know the size of an array at compile time. So the compiler is setting aside memory for an integer array with one element and then the dynamic part of your code is attempting to redeclare it a run-time. Try moving a outside the while loop and declaring it with a well defined maximum number of integer values like:
#define MAX_NUMS 1000
int a[MAX_NUMS];
There are some other problems as listed above, but I tested this with GCC 4.9 compiler and it seems to give the desired result.
You are doing some unnecessary matter.
You have to check just this--
while(input_number)
{
if(input_number==42)
break;
else
printf("%d\n",input_number);
}
In my thought I had edited your code to store all number before 42 based on your code.
#include<stdio.h>
int main()
{
int i=1,j,temp;
int a[10010];
printf("enter numbers:\n");
while(i)
{
scanf("%d",&temp);
i++;
a[i-2]=temp;
if(temp==42)
{
for(j=0; j<i-2; j++)
{
if(a[j]==42)
break;
else
printf("%d\n",a[j]);
}
}
if (temp == 42)
break;
}
return 0;
}
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;
}
}