Splitting C linked list without making a copy - c

I have this struct:
typedef struct node {
struct node *m_Next;
int id;
} NODE;
And I need to split linked list in half. If it can't be split into two same halves, I want to remove the last one from the bigger list.
Example: The whole list: {1,2,3,4,5}; What I need: A:{1,2} B:{3,4} (The last one is discarded)
I have this function to separate the list:
void split(NODE *src, NODE **p1, NODE **p2) {
int len = get_length(src);
if (len < 2) {
*p1 = NULL;
*p2 = NULL;
return;
}
struct node *current = src;
int c = (len - 1) / 2;
for (int i = 0; i < c; i++) {
current = current->m_Next;
}
*p1 = src;
*p2 = current->m_Next;
current->m_Next = NULL;
}
It works fine with even lists, but when I try to separate something with 7 structs, I have two problems:
a) The last one doesn't point to NULL
b) It shuffles the data somehow (I expect: A:{1,2,3} B:{4,5,6} | I get: A:{1,2,3} B:{5,4,7} for example)
Could anyone please help me splitting the list correctly and adding the even/odd condition?
I already have the function to delete the last struct:
deleteNode(struct TSoldier *firstNode)
I just don't use it currently, because the split function is bugged.
Thanks :)

First of all, it is worth noting that the following code probably causes a memory leak:
if (len < 2) {
*p1 = NULL;
*p2 = NULL;
return;
}
If the number of nodes is equal to 1, then, unless you keep some other reference to this node, the memory will be leaked. You probably have such a reference outside the function, but you are probably discarding this reference and only keeping the values written to p1 and p2, which means the memory is leaked.
Therefore, assuming that you allocated the node with malloc, you will probably want to add the line
free( src );
in order to prevent the memory leak, or use your function deleteNode.
As already pointed out in the other answer, the line
int c = (len - 1) / 2;
is wrong. It should be:
int c = len / 2 - 1;
At the end of your function split, if the number of nodes is odd, you must add code to discard the final node, for example like this:
if ( len % 2 == 1 )
{
current = *p2;
for (int i = 0; i < c; i++) {
current = current->m_Next;
}
free( current->m_Next );
current->m_Next = NULL;
}

To determine the last node of the first half, instead of int c = (len - 1) / 2; you should use this formula that works for even and odd lengths:
int c = len / 2 - 1;
Similarly, to drop the last node if the length is odd and greater than 1:
if (len & 1) {
NODE *node = src;
for (int i = 2; i < len; i++) {
node = node->m_Next;
}
deleteNode(node->m_Next);
node->m_Next = NULL;
}
Here is an alternative approach using the fast and slow scan trick:
void split(NODE *src, NODE **p1, NODE **p2) {
NODE *last = src;
*p1 = *p2 = NULL;
if (src && src->m_Next) {
NODE *slow = src;
NODE *fast = src;
while (fast->m_Next && fast->m_Next->m_Next) {
slow = slow->m_Next;
fast = fast->m_Next->m_Next;
}
*p1 = src;
*p2 = slow->m_Next;
slow->m_Next = NULL;
last = fast->m_Next; // last will be non NULL if length is odd
fast->m_Next = NULL;
}
if (last) {
deleteNode(last); // drop the last node if required
}
}

Related

counting redundancies in linked list in C

I'm practicing code that can find redundancies in a linked list.
For example:
INPUT
777
OUTPUT
contains 2 redundancies
INPUT
32182
OUTPUT
contains 1 redundancies
I'm struggling to actually track redundancies in my code. I'v sorted the linked list, then I assume I would just create 2 pointers one that traverses the current location of the linked list and one that traverses the previous location of the linked list and if they're equal count++. But I always get 0 redundancies.
In the code below, I think my challenge is mainly in the countRedun() method.
struct digit * insertAtFront(struct digit *start, struct digit * newDig){
struct digit * ptr = start;
newDig = start;
return newDig;
}
struct digit * insertIntoSorted(struct digit *start, struct digit *newDig) {
struct digit *ptr = start;
struct digit *prev = NULL;
while ((ptr!=NULL) && (ptr->num < newDig->num)) {
prev = ptr;
ptr = ptr->next;
}
if (prev == NULL) {
start = insertAtFront(start, newDig);
} else {
prev->next = newDig;
newDig->next = ptr;
}
return(start);
}
struct digit * sortedCopy(struct digit * start) {
//! heap1=showMemory(start=348, cursors=[start, ptr, sortedStart, newDigit])
//! heap2=showMemory(start=519, cursors=[start, newDigit, ptr, prev])
struct digit *ptr = start;
struct digit *sortedStart = NULL;
struct digit *newDigit;
if (start!=NULL) {
sortedStart = createDigit(start->num);
ptr = ptr->next;
}
while (ptr!=NULL) {
newDigit = createDigit(ptr->num);
sortedStart = insertIntoSorted(sortedStart, newDigit);
ptr = ptr->next;
}
return(sortedStart);
}
int countRedun(struct digit * start){
struct digit *sorted, *ptr, *prev, * curr;
ptr = start;
prev = start;
//sort linked list
sorted = sortedCopy(start);
int count = 0;
while(ptr != NULL)
{
if(ptr->num == prev->num)
{
count++;
}
prev = ptr;
ptr = ptr->next;
}
}
I've excluded the code that asks user for input, as well as the linked list creator methods, assuming that the sorting, and counting methods are key for this question.
It looks like sortedCopy makes a whole new list, but sorted. If so, then you need to reorder:
ptr = start;
prev = start;
//sort linked list
sorted = sortedCopy(start);
with:
//sort linked list
sorted = sortedCopy(start);
ptr = sorted;
prev = sorted;
as a note, you would likely be better to:
prev = NULL;
while(ptr != NULL) {
count += (prev && ptr->num == prev->num);
prev = ptr;
ptr = ptr->next;
}
otherwise you count will always be off by one.
I think the issue is in insertAtFront
struct digit * insertAtFront(struct digit *start, struct digit * newDig){
struct digit * ptr = start;
newDig = start;
return newDig;
}
Remember that everything is passed by value. Your ptr variable isn't used at all, and in this function start and newDig are local variables. Really this is equivalent to:
struct digit * insertAtFront(struct digit *start, struct digit * newDig){
return start;
}
Have another look at that function. I'm not sure of your context but you can use a debugger or printf statements to see what's going on.
If you are sure that:
all you need to do is get the number of redundancies
your input is always going to be a digit between 0 and 9
Then you don't need to sort the data (which, by the way, you're doing in O(n^2) time complexity).
All you need to do is keep an array with 10 elements initialized to 0, increase the corresponding index to your element and count the elements with value greater than 1.
Something along the lines of this (beware: NOT tested):
int countRedun(struct digit * start){
int counter[10] = {0};
struct digit *ptr = start;
int total = 0;
while(ptr != NULL)
{
counter[ptr->num]++;
ptr = ptr->next;
}
for (int i = 0; i < 10; i++) {
if (counter[i] > 1) {
total += counter[i] - 1;
}
}
return total;
}

CS50 - LOAD - Get random character from no where when trying to execute load

I am new to C programming. I am trying to do the pset5 in CS50 while trying to understand the concepts of memory, linked list and hashtable. I wrote the code and it compiled but there seems to be something wrong because every time I tried to execute the code it returns some garbage value. Could anyone please help me with that? Many thanks.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
#include "dictionary.h"
#define DICTIONARY "dictionaries/small"
typedef struct node
{
char WORD[LENGTH + 1];
struct node *next;
}
node;
int hash(char *word);
int main(void)
{
node **HASHTABLE = malloc(sizeof(node) * 26);
//open the dictionary
FILE *dic = fopen(DICTIONARY, "r");
if (dic == NULL)
{
fprintf(stderr, "Could not open the library\n");
return 1;
}
int index = 0;
char word[LENGTH + 1];
for (int c = fgetc(dic); c != EOF; c = fgetc(dic))
{
word[index] = c;
index++;
if (c == '\n')
{
int table = hash(word);
printf("%d\n", table);
//create a newnode
node *newnode = malloc(sizeof(node));
strcpy(newnode->WORD, word);
newnode->next = NULL;
printf("Node: %s\n", newnode->WORD);
index = 0;
//add new node to hash table
if (HASHTABLE[table] == NULL)
{
HASHTABLE[table] = newnode;
}
else
{
HASHTABLE[table]->next = newnode;
}
}
}
for(int i = 0; i < 26; i++)
{
node *p = HASHTABLE[i];
while (p != NULL)
{
printf("%s", p->WORD);
p = p->next;
}
}
//free memory
for(int i = 0; i < 26; i++)
{
node *p = HASHTABLE[i];
while (p != NULL)
{
node *temp = p->next;
free(p);
p = temp;
}
}
free(HASHTABLE);
}
int hash(char *word)
{
int i = 0;
if (islower(word[0]))
return i = word[0] - 'a';
if (isupper(word[0]))
return i = word[0] - 'A';
return 0;
}
Your code has serious problems that result in undefined behavior.
Two of them are the result of this line:
node **HASHTABLE = malloc(sizeof(node) * 26);
That allocates 26 node structures, but the HASHTABLE variable expects the address of a pointer to an array of node * pointers (that's the ** in the node **HASHTABLE declaration).
So, you should replace it with something like:
node **HASHTABLE = malloc( 26 * sizeof( *HASHTABLE ) );
Note that I used the dereferenced value of the variable being assigned to - HASHTABLE. This means in this case a node (one less * than in the declaration). So if the type of HASHTABLE changes, you don't need to make any other changes to the malloc() statement.
That problem, while technically undefined behavior, likely wouldn't cause any problems.
However, there's still a problem with
node **HASHTABLE = malloc( 26 * sizeof( *HASHTABLE ) );
that will cause problems - and serious ones.
That array of 26 pointers isn't initialized - you don't know what's in them. They can point anywhere. So this won't work well, if at all:
if (HASHTABLE[table] == NULL)
Meaning this points off to somewhere unknown:
HASHTABLE[table]->next = newnode;
And that will cause all kinds of problems.
The simplest fix? Initialize the values all to zero by using calloc() instead of malloc():
node **HASHTABLE = calloc( 26, sizeof( *HASHTABLE ) );
Until that's fixed, any results from your entire program are questionable, at best.
The reason for the garbage is that you didn't null-terminate the string:
strcpy(newnode->WORD, word);
strcpy expects the src to point to a null-terminated string. Simply adding 0 at the end. Simply terminate it with
word[index] = 0;
before the strcpy.
Other than that, the ones in Andrew Henle's answer should be addressed too, but I am not going to repeat them here.
BTW, next you will notice that
HASHTABLE[table]->next = newnode;
wouldn't work properly - that code always inserts the node as the 2nd one. But you want to always insert the new node unconditionally as the head, with
newnode->next = HASHTABLE[table];
HASHTABLE[table] = newnode;
There need not be any special condition for inserting the first node to a bucket.

How to free memory occupied by a Tree, C?

I'm currently dealing with a generic Tree with this structure:
typedef struct NODE {
//node's keys
unsigned short *transboard;
int depth;
unsigned int i;
unsigned int j;
int player;
int value;
struct NODE *leftchild; //points to the first child from the left
struct NODE *rightbrothers; //linked list of brothers from the current node
}NODE;
static NODE *GameTree = NULL;
While the function that allocates the different nodes is (don't bother too much at the keys' values, basically allocates the children-nodes. If there aren't any the new child goes to leftchild, otherwise it goes at the end of the list "node->leftchild->rightbrothers"):
static int AllocateChildren(NODE **T, int depth, unsigned int i, unsigned int j, int player, unsigned short *transboard) {
NODE *tmp = NULL;
if ((*T)->leftchild == NULL) {
if( (tmp = (NODE*)malloc(sizeof(NODE)) )== NULL) return 0;
else {
tmp->i = i;
tmp->j = j;
tmp->depth = depth;
(player == MAX ) ? (tmp->value = 2 ): (tmp->value = -2);
tmp->player = player;
tmp->transboard = transboard;
tmp->leftchild = NULL;
tmp->rightbrothers = NULL;
(*T)->leftchild = tmp;
}
}
else {
NODE *scorri = (*T)->leftchild;
while (scorri->rightbrothers != NULL)
scorri = scorri->rightbrothers;
if( ( tmp = (NODE*)malloc(sizeof(NODE)) )== NULL) return 0;
else {
tmp->i = i;
tmp->j = j;
tmp->depth = depth;
(player == MAX) ? (tmp->value = 2) : (tmp->value = -2);
tmp->player = player;
tmp->transboard = transboard;
tmp->leftchild = NULL;
tmp->rightbrothers = NULL;
}
scorri->rightbrothers = tmp;
}
return 1;
}
I need to come up with a function, possibly recursive, that deallocates the whole tree, so far I've come up with this:
void DeleteTree(NODE **T) {
if((*T) != NULL) {
NODE *tmp;
for(tmp = (*T)->children; tmp->brother != NULL; tmp = tmp->brother) {
DeleteTree(&tmp);
}
free(*T);
}
}
But it doesn't seem working, it doesn't even deallocate a single node of memory.
Any ideas of where I am being wrong or how can it be implemented?
P.s. I've gotten the idea of the recursive function from this pseudocode from my teacher. However I'm not sure I've translated it correctly in C with my kind of Tree.
Pseudocode:
1: function DeleteTree(T)
2: if T != NULL then
3: for c ∈ Children(T) do
4: DeleteTree(c)
5: end for
6: Delete(T)
7: end if
8: end function
One thing I like doing if I'm allocating lots of tree nodes, that are going to go away at the same time, is to allocate them in 'batches'. I malloc then as an array of nodes and dole them out from a special nodealloc function after saving a pointer to the array (in a function like below). To drop the tree I just make sure I'm not keeping any references and then call the free routine (also like below).
This can also reduce the amount of RAM you allocate if you're lucky (or very smart) with your initial malloc or can trust realloc not to move the block when you shrink it.
struct freecell { struct freecell * next; void * memp; } * saved_pointers = 0;
static void
save_ptr_for_free(void * memp)
{
struct freecell * n = malloc(sizeof*n);
if (!n) {perror("malloc"); return; }
n->next = saved_pointers;
n->memp = memp;
saved_pointers = n;
}
static void
free_saved_memory(void)
{
while(saved_pointers) {
struct freecell * n = saved_pointers;
saved_pointers = saved_pointers->next;
free(n->memp);
free(n);
}
}
I've just realized my BIG mistake in the code and I'll just answer myself since no one had found the answer.
The error lies in this piece of code:
for(tmp = (*T)->children; tmp->brother != NULL; tmp = tmp->brother) {
DeleteTree(&tmp);
}
First of all Ami Tavory was right about the for condition, i need to continue as long as tmp != NULL
Basically it won't just work because after the DeleteTree(&tmp), I can no longer access the memory in tmp because it's obviously deleted, so after the first cycle of for ends I can't do tmp = tmp->rightbrother to move on the next node to delete because tmp->rightbrother no longer exists as I just deleted it.
In order to fix it I just needed to save the tmp->brother somewhere else:
void DeleteTree(NODE **T) {
if((*T) != NULL) {
NODE *tmp, *deletenode, *nextbrother;
for(tmp = (*T)->children; tmp != NULL; tmp = nextbrother) {
nextbrother = tmp->rightbrother;
DeleteTree(&tmp);
}
canc = (*T);
free(*T);
(*T) = NULL;
}
}
Just for the sake of completeness I want to add my version of DeleteTree
void DeleteTree(NODE *T) {
if(T != NULL) {
DeleteTree(T->rightbrothers);
DeleteTree(T->leftchild);
free(T);
}
}
I think it is much less obscure and much easier to read. Basically it solves the issue in DeleteTree but through eliminating the loop.
Since we free the nodes recursively we might as well do the whole process recursively.

Selection sort with linked list's

I have the following data structure:
struct scoreentry_node {
struct scoreentry_node *next;
int score;
char name[1];
};
typedef struct scoreentry_node *score_entry;
I am trying to create a function that consumes my structure in order and arranges them in ascending order based on the name. I want to modify the input without allocating any memory or freeing anything:
I've tried your suggestions:
void selectionsort(score_entry *a) {
for (; *a != NULL; *a = (*a)->next) {
score_entry *minafteri = a;
// find position of minimal element
for (score_entry j = (*a)->next; j != NULL; j = j->next) {
if (strcmp(j->name, (*minafteri)->name) == -1) {
*minafteri = j;
}
}
// swap minimal element to front
score_entry tmp = *a;
a = minafteri;
*minafteri = tmp;
}
}
I'm testing the above code with the following:
score_entry x = add(8, "bob", (add( 8 , "jill", (add (2, "alfred", NULL)))));
iprint("",x);
selectionsort(&x);
iprint("", x);
clear(x); //Frees the whole list
iprint() prints the score and name fields in the struct. My add function is as follows:
score_entry add(int in, char *n, score_entry en) {
score_entry r = malloc(sizeof(struct scoreentry_node) + strlen(n));
r->score = in;
strcpy(r->name, n);
r->next = en;
return r;
}
I'm getting heap errors and my second print doesn't print the sorted list, it prints nothing. What am I doing wrong, and what can I do to fix it?
besides passing the pointer by address (see comments below) you also need to fix the way you swap elements too
void selectionsort(score_entry *a) {
for (; *a != NULL; *a = (*a)->next)
{
score_entry *minafteri = a;
// find position of minimal element
for (score_entry j = (*a)->next; j != NULL; j = j->next) {
if (strcmp(j->name, (*minafteri)->name) == -1) {
*minafteri = j;
}
}
// swap minimal element to front
score_entry tmp = *a;
a = minafteri; // put the minimal node to current position
tmp->next = (*a)->next ; //fix the links
(*minafteri)->next=tmp; //fix the links
}
}
You have to pass the argument to selectionsort by reference:
void selectionsort(score_entry *a) {
for (; *a != NULL; *a = (*a)->next)
{
score_entry *minafteri = a;
// find position of minimal element
for (score_entry j = (*a)->next; j != NULL; j = j->next) {
if (strcmp(j->name, (*minafteri)->name) == -1) {
*minafteri = j;
}
}
// swap minimal element to front
score_entry tmp = *a;
a = minafteri;
*minafteri = tmp;
}
}
This code is hideous! Not only have you not provided us with all of the necessities to reproduce your problem (we can't compile this!), but you've hidden pointer abstractions behind typedef (also a nightmare for us). Generally speaking, one shouldn't even use linked lists in C anymore let alone sort them...
Nonetheless, there are two answers here.
*minafteri = j; found within your find loop actually modifies your list! Why should your find loop be modifying your list?
Answer: it shouldn't! By instead assigning minafteri = &j->next, you won't be modifying the list with your find loop...
Alternatively, you could perform the swap inside of that loop.
*minafteri = j; would need to swap the following, in this order:
(*minafteri)->next and j->next
*minafteri and j
Do you think that single line of code is capable of performing those two swaps? Well, it gets half way through one of them... and removes a heap of elements from your list in the process!
The following appears to be a faulty attempt swapping elements:
score_entry *minafteri = a; // half of assigning `a` to `a`
/* SNIP!
* Nothing assigns to `minafteri` in this snippet.
* To assign to `minafteri` write something like `minafteri = fubar;` */
score_entry tmp = *a; // half of assigning `*a` to `*a`
a = minafteri; // rest of assigning `a` to `a`
*minafteri = tmp; // rest of assigning `*a` to `*a`
It's really just assigning *a to *a and a to a... Do you think you need to do that?
I'd have thought you'd notice that when you were creating your MCVE... Ohh, wait a minute! Shame on you!
Focus on swapping two nodes within a list as a smaller task. Once you've done that, consider taking on this task.
There are multiple problems in your code:
if (strcmp(j->name, (*minafteri)->name) == -1) { is incorrect: strcmp() does not necessarily return -1 when the first string is less than the second, it can return any negative value.
The way you adjust the links in order to move the lower entry is incorrect: you cannot update the link from the previous node to the one you move to the start. The list is corrupted.
Here is an improved version:
void selectionsort(score_entry *a) {
for (; *a != NULL; a = &(*a)->next) {
// find position of minimal element
score_entry *least = a;
for (score_entry *b = &(*a)->next; *b != NULL; b = &(*b)->next) {
if (strcmp((*b)->name, (*least)->name) < 0) {
least = b;
}
}
if (least != a) {
// swap minimal element to front
score_entry n = *least;
*least = n->next; /* unlink node */
n->next = *a; /* insert node at start */
*a = n;
}
}
}
Here is the Java Implementation of Selection Sort on Linked List:
Time Complexity: O(n^2)
Space Complexity: O(1) - Selection sort is In-Place sorting algorithm
class Solution
{
public ListNode selectionSortList(ListNode head)
{
if(head != null)
{
swap(head, findMinimumNode(head));
selectionSortList(head.next);
}
return head;
}
private void swap(ListNode x, ListNode y)
{
if(x != y)
{
int temp = x.val;
x.val = y.val;
y.val = temp;
}
}
private ListNode findMinimumNode(ListNode head)
{
if(head.next == null)
return head;
ListNode minimumNode = head;
for(ListNode current = head.next; current != null; current = current.next)
{
if(minimumNode.val > current.val)
minimumNode = current;
}
return minimumNode;
}
}

Printing deletes the value from my linked list

As a part of an assignment, I need to write two functions:
a function that sums up two natural numbers represented as a linked list
a functions that prints a number represented in the same way.
for some reason, both function work perfectly fine separately, but when I try to use the print function on the result of the sum function, it changes the value of the sum right in the beginning of the print function , and prints the wrong value. when I use printf to print the same value in the main, there is no problem. my code is detailed below. any ideas?
void main()
{
int a[1] = { 1 },
b[1] = { 2 };
int * *pa, **pb;
List lst1, lst2;
List sum;
pa = (int * *) malloc(sizeof(int * )); * pa = &a[0];
pb = (int * *) malloc(sizeof(int * )); * pb = &b[0];
lst1 = arrToList(pa, 1);
lst2 = arrToList(pb, 1);
addNumbers(lst1, lst2, &sum);
//printf("%d\n",*(sum.head->dataPtr));
printNumber(sum);
}
//a function that recieves a number represented ad a list and prints it
void printNumber(List num)
{
ListNode * curr;
int currData,
i,
number;
if (isEmptyList(num) == TRUE)
printf("the input was an empty list, nothing to print");
else
{
i = 0;
number = 0;
curr = num.head;
while (curr != NULL)
{
currData = *(curr - >dataPtr);
number = number + currData * ((int) pow(10, i));
curr = curr - >next;
i++;
}
printf("%d \n", number);
}
}
// a function that sums in list
// representation two numbers,
// each represented as a list
void addNumbers(List n1, List n2, List * sum)
{
ListNode * currN1;
ListNode * currN2;
ListNode * currSum;
int currN1N2Sum; //stores the sum of the current digits in n1 and n2
int carrier,
prevCarrier; //current and previous carriers that carries +1 to the
next digit of sum
if the lst sum was bigger then 9
if ((isEmptyList(n1) == TRUE) || (isEmptyList(n2) == TRUE))
printf("bad input =(");
else
{
currN1 = n1.head;
currN2 = n2.head; * sum = createEmptyList();
carrier = 0;
prevCarrier = 0;
while ((currN1 != NULL) && (currN2 != NULL))
{
currN1N2Sum = *(currN1->dataPtr) + *(currN2->dataPtr) + prevCarrier;
if (currN1N2Sum > 9)
{
carrier = 1;
currN1N2Sum = currN1N2Sum - 10;
}
currSum = creatNewListNode( & currN1N2Sum, NULL);
insertNodeToEnd(sum, currSum);
prevCarrier = carrier;
carrier = 0;
currN1 = currN1 - >next;
currN2 = currN2 - >next;
} //while ((currL1!=NULL)&&(currL2!=NULL))
while (currN1 != NULL)
{
currN1N2Sum = *(currN1 - >dataPtr) + prevCarrier;
currN1 = currN1 - >next;
if (prevCarrier != 0) prevCarrier = 0;
}
while (currN2 != NULL)
{
currN1N2Sum = *(currN2 - >dataPtr) + prevCarrier;
currN2 = currN2 - >next;
if (prevCarrier != 0) prevCarrier = 0;
}
} // ! ((isEmptyList(n1)==TRUE)||(isEmptyList(n2)==TRUE))
}
here is the rest of the code:
typedef struct listNode{
int* dataPtr;
struct listNode* next;
} ListNode;
typedef struct list
{
ListNode* head;
ListNode* tail;
} List;
List createEmptyList()//creates and returns an empty linked list
{
List res;
res.head = res.tail = NULL;
return res;
}
Bool isEmptyList ( List lst )//checks if a given list is empty or not
{
if (lst.head == NULL && lst.tail == NULL)
return TRUE;
else
return FALSE;
}
void insertDataToEnd ( List * lst, int *dataPtr ) //inserts new data to the end of an existing linked list
{
ListNode * newTail;
newTail = creatNewListNode ( dataPtr, NULL );
insertNodeToEnd(lst,newTail);
}
void insertNodeToEnd ( List * lst, ListNode * newTail )//insert an existing node to an existing linked list
{
if (isEmptyList(*lst) == TRUE )
insertNodeToStart ( lst,newTail );
else
{
(*lst).tail -> next = newTail;
newTail->next = NULL;
(*lst).tail = newTail;
}
}
ListNode * creatNewListNode ( int * dataPtr, ListNode * next )//inserts new node in an existing linked list
{
ListNode * res;
res = (ListNode *) malloc (sizeof(ListNode));
res -> dataPtr = dataPtr;
res -> next = next;
return res;
}
void insertNodeToStart ( List * lst, ListNode * newHead )//inserts node to the begining of a given linked list
{
if ( isEmptyList( *lst ) == TRUE )
{
(*lst).head = newHead;
(*lst).tail = newHead;
newHead -> next = NULL;
}
else
{
newHead -> next = (*lst).head;
(*lst).head = newHead;
}
}
The bug is in the function addNumbers.
When you add a node to store the sum you pass a pointer to the variable currN1N2Sum which is a local variable (stored on the stack). When the addNumbers function terminates, the storage of the local variable is set free. The value found at that location will remain unchanged and thus apparently valid as long as the storage is not reused.
This is why you had the impression the addNumbers function was correct. When calling the printNumber function the storage is overwritten and you find a different value in there.
This explain your bug.
There is another problem with addNumbers. When you will try to add two digit numbers, the content of the currN1N2Sum will be overwritten by a new value.
What you should do is allocate a buffer (malloc) and store the value contained into currN1N2Sum into it. Pass the pointer to the buffer into the new node.
BTW: you may change (*lst).head in lst->head. It will make your code more readable.
We need to see some more code: how you define the data structure for holding nodes, how you add nodes etc.
The following line is suspect:
number=number+currData*((int)pow(10,i));
Say, you have 123 stored as 1, 2, and 3 nodes:
number = 0;
number = 0 + 1 * 1 = 1;
number = 1 + 2 * 10 = 21;
number = 21 + 3 * 100 = 321;
But if you store is as 3, 2, and 1 nodes you'd get:
number = 0;
number = 0 + 3 * 1 = 3;
number = 3 + 2 * 10 = 23;
number = 23 + 1 * 100 = 123;
Is this your problem?
I'm not if this is an issue or not without seeing the implementation of createNewListNode(), but here's something to think about:
Where are the dataPtrs in the sum list pointing after you return from the addNumbers() call?
You've got a problem with createEmptyList. you declare there a list called res and return the structure but the minute this function returns that structure is not valid any more.
try using malloc (for the struct) and then return the pointer to the caller. You use this function in the beginning with *sum.
This is a similar bug to what chmike found so you better fix both.
I think you might be messing things up pointer-wise... The way you're allocating the list 'sum' in addNumbers seems very, very odd. (And I would not be surprised if it's breaking things...)
Try making these changes:
In main:
List *sum;
<...>
addNumbers(lst1,lst2,sum); //Note the absence of the reference operator &
printNumbers(*sum);
(Alternatively, change printNumbers to accept a (List *) instead of (List)).
Hope this helped XD
EDIT:
Try allocating 'sum' before making calls to addNumbers().
lst1 = arrToList(pa, 1);
lst2 = arrToList(pb, 1);
sum = createEmptyList();
I still think the way that your data structures are a little weird :S

Resources