I am trying to find the smallest two numbers in a linked list in C++ (without using any built-in functions).
I tried to do so as below:
My logic is:
(1) Assume the first node in the linked list is minimum1 and the second is minimum2. Compare them. The greater becomes minimum2 and the smaller becomes minimum1.
(2) Start from the third node (third because we have already covered first and second) in a while loop until we reach NULL, thus traversing all the list.
(3) Compare the newly traversed node with minimum1 and minimum2. If this node is smaller than minimum1, then put its value in minimum1. minimum2 now will contain the value of minimum1, and minimum1 will contain the value of the newly found node which was smaller than minumum1.
Below is my code which takes the number of nodes to be created, reads the values of all nodes continuously (just keep on pressing Enter after every number), and creates the linked list from all the nodes. These are working fine.
Code
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct node
{
int freq;
struct node* next;
};
typedef struct node node;
node* tree;
// Finding minimum two elements:
void find_two_min(node** List, node** lmin1, node** lmin2)
{
int i;
node* temp = *List;
node *min1, *min2;
node* var1 = *List;
node* second = (*List)->next;
if (var1 > second)
{
min2 = var1;
min1 = second;
}
else
{
min1 = var1;
min2 = second;
}
while (temp->next->next->next != NULL)
{
if (temp->freq < min2->freq)
{
min1 = min2;
min2 = temp;
}
else if (temp->freq < min1->freq)
{
min1 = temp;
}
temp = temp->next;
}
*lmin1 = min1;
*lmin2 = min2;
}
void main()
{
int size, data;
node *min1, *min2;
int count = 0; // This flag is to check whether it's the first node inside the do-while loop.
tree = NULL;
printf("Enter the number of nodes:\n");
scanf("%d", &size);
printf("Enter the elements:\n");
node* prev;
do
{
scanf("%d", &data);
if (count == 0)
{
node* temp;
temp = (node*) malloc(sizeof(node));
temp->freq = data;
temp->next = NULL;
prev = temp;
tree = prev;
}
else
{
node* temp;
temp = (node*) malloc(sizeof(node));
temp->freq = data;
temp->next = NULL;
prev->next = temp;
prev = prev->next;
}
--size;
++count;
}
while (size > 0);
printf("Printing linked list:\n");
node* temp1;
temp1 = tree;
while (temp1 != NULL)
{
printf("%d, ", temp1->freq);
temp1 = temp1->next;
}
node* temp5 = tree;
find_two_min(&temp5, &min1, &min2);
printf("\nThe two minimum numbers are min1: %d and min2: %d.\n", min1->freq, min2->freq);
}
My code doesn't work on the following input (it gives the wrong output):
Enter the number of nodes:
4
Enter the elements:
0
-5
-2
8
Printing linked list:
0, -5, -2, 8,
The two minimum numbers are min1: 0 and min2: -5.
It was supposed to print "min1: -5" and "min2: -2" but I don't know why it doesn't.
Could anyone please help me eliminate this problem? Any algorithm or piece of code in C/C++ to use as a reference is appreciated. Thanks.
Note: I can't use any built-in functions.
If trying to do 2 things at once confuses you,
then do only 1 thing,
AND LATER, follow that with another singular effort.
i.e.
1st - write search1() to find the smallest item and record the node pointer.
2nd - write search2() to find the smallest item, but add to your search2 the idea to compare the node address to the previously found smallest node. And when already found, skip it as if was not even there.
Implement search1, debug it, and get that working.
AFTER THAT
Implement search2, (probably a copy) and pass in the node pointer found in the search1.
Each time you find a possible update to the search2's smallest node,
insert a test to determine if this node matches the previously found
You have a bug in the line
if(var1>second)
This is comparing the memory addresses of the two nodes, not their frequencies!
There's another bug in the line
if(temp->freq<min2->freq)
and the later line
else if(temp->freq<min1->freq)
The code inside the if statement block following the first line behaves as though you compared temp->freq with min1->freq, not min2->freq as you're currently doing -- and vice versa for the code inside the else if statement block following the second line.
Have two ints min1, min2, both INT_MAX (from limits.h). (Assumption: No element can have the value INT_MAX.)
Walk through your list, one by one. For each element do:
If it is smaller than min1 then min1 is now the second smallest ever, so assign min1 to min2. Then replace min1 with the element.
If it is not smaller than min1 but smaller than min2, it replaces min2.
If none of the above, skip element.
After iterating the list min1 will hold the smallest list value, min2 the second smallest. If min2 is INT_MAX, the list had only one element. If min1 is INT_MAX, the list was empty.
I don't have a full answer for you, but I don't trust checking temp->next->next->next!=NULL in a while loop. That's going to have problems with short lists.
You might be better off looking at one item at a time. Set your two min values to maximum possible value (i.e. INT_MAX) and the node pointers to NULL.
If the value of the first item on the list is less than one of your two min values, update the min value and node pointer.
If the value of the next item on the list is less than one of your two min values, update the min value and the node pointer. You may need to rearrange the order of the min values.
Repeat until you've looked at every item in the list.
You should have your answer when you get to the end of the list and the pointer manipulation will be easier to trace/debug.
I have done the solution of my question using INT_MAX. It works fine:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <limits.h>
struct node
{
int freq;
struct node * next;
};
typedef struct node node;
node * tree;
//Problem creating area is below (code for finding minimum two elements)
void find_two_min(node * * List, node * * lmin1, node * * lmin2)
{
node * temp = * List;
node * min1;
min1 = (node*) malloc(sizeof(node));
min1 -> freq = INT_MAX;
node * min2;
min2 = (node*) malloc(sizeof(node));
min2 -> freq = INT_MAX; //This initialisation of INT_MAX to min2->freq creates problem because printf() statment above it works well but don't work below it.
printf("check1\n");
while (temp != NULL)
{
printf("\ncheck2\n");
if ((temp) -> freq < min2 -> freq)
{
printf("check3\n");
min1 = min2;
min2 = temp;
}
else if ((temp) -> freq < min1 -> freq && (temp) -> freq != min2 -> freq)
{
printf("check4\n");
min1 = temp;
}
temp = temp -> next;
}
* lmin1 = min1;
* lmin2 = min2;
printf("address of min2 is : %d and value is %d \n" ,min2, min2->freq);
printf("check5\n");
}
//Problem creating area is above//
void main()
{
int size, data;
node * min1;
node * min2;
int count = 0; //this count flag is to check is it's first node or not inside the do-while loop.
tree = NULL;
printf("enter the size of node\n");
scanf("%d", & size);
printf("start entering the number of elements until your size\n");
node * prev;
do {
scanf("%d", & data);
if (count == 0)
{
node * temp;
temp = (node * ) malloc(sizeof(node));
temp -> freq = data;
temp -> next = NULL;
prev = temp;
tree = prev;
}
else
{
node * temp;
temp = (node * ) malloc(sizeof(node));
temp -> freq = data;
temp -> next = NULL;
prev -> next = temp;
prev = prev -> next;
}
size--;
++count;
}
while (size > 0);
printf("Printing linked list\n");
node * temp1;
temp1 = tree;
while (temp1 != NULL)
{
printf("%d-> ", temp1 -> freq);
temp1 = temp1 -> next;
}
node * temp5 = tree;
find_two_min( & temp5, & min1, & min2);
printf("\n The two minimum numbers are min1 :%d and min2 : %d\n", min1 -> freq, min2 -> freq);
}
This should do it:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct node {
int freq;
struct node* next;
};
typedef struct node node;
//Function Prototype
void find_two_min(node**, node**, node**);
void main() {
node* min1 = (node*) malloc(sizeof(node));
node* min2 = (node*) malloc(sizeof(node));
node* tree = NULL;
node* prev;
node* temp1;
node* temp;
node* temp5 = tree;
int size, data;
int count = 0; //this count flag is to check is it's first node or not inside the do-while loop.
printf("enter the size of node\n");
scanf("%d", &size);
printf("start entering the number of elements until your size\n");
do {
scanf("%d", & data);
if (count == 0) {
temp = (node*) malloc(sizeof(node));
temp->freq = data;
temp->next = NULL;
prev = temp;
tree = prev;
} else {
node* temp;
temp = (node*) malloc(sizeof(node));
temp->freq = data;
temp->next = NULL;
prev->next = temp;
prev = prev->next;
}
size--;
++count;
} while (size > 0);
printf("Printing linked list\n");
temp1 = tree;
while (temp1) {
printf("%d-> ", temp1->freq);
temp1 = temp1->next;
}
if (count > 1) {
find_two_min(&tree, &min1, &min2);
printf("\n The two minimumnumbers are min1 :%d and min2 : %d\n",min1->freq,min2->freq);
} else
printf("\n Not enough data\n\n");
}
//Function Definition
void find_two_min(node** List,node** lmin1,node** lmin2) {
node* temp = *List;
node* min1;
node* min2;
node* var1 = *List;
node* second=(*List)->next;
/* OLD ONE
if (var1->freq > second->freq) {
min2 = var1;
min1 = second;
} else {
min1 = var1;
min2 = second;
}
*/
if (var1->freq > second->freq) {
min1 = var1;
min2 = second;
} else {
min2 = var1;
min1 = second;
}
while(temp->next) {
printf("\nCurrent freq is %d", temp->freq);
printf("\nNext freq is %d", (temp->next)->freq);
if ((temp->next)->freq < min2->freq) {
printf("\n Condition one is fulfilled");
min1 = min2;
min2 = temp->next;
} else if ((temp->next)->freq < min1->freq) {
printf("\n Condition two is fulfilled");
min1 = temp->next;
}
temp = temp->next;
}
*lmin1 = min1;
*lmin2 = min2;
}
Related
i have been trying to solve this problem by using binary trees, because i am starting to learn about them.
Please tell me if this problem can be solved by using binary trees or not, and if yes, what's wrong with my code for it that i've written so far(its in c++)?
it gives wrong answer...
The Problem:
Vasya has found a strange device. On the front panel of a device there are: a red button, a blue button and a display showing some positive integer. After clicking the red button, device multiplies the displayed number by two. After clicking the blue button, device subtracts one from the number on the display. If at some point the number stops being positive, the device breaks down. The display can show arbitrarily large numbers. Initially, the display shows number n.
Bob wants to get number m on the display. What minimum number of clicks he has to make in order to achieve this result?
Input
The first and the only line of the input contains two distinct integers n and m (1 ≤ n, m ≤ 104), separated by a space .
Output
Print a single number — the minimum number of times one needs to push the button required to get the number m out of number n.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
struct Node{
int val;
Node* Left;
Node* Right;
};
Node* GetNode(int val){
Node* newnode = new Node();
newnode->val = val;
newnode->Left = NULL;
newnode->Right = NULL;
return newnode;
}
int BFS(Node* root, int m){
int ctr = 0;
queue<Node*> qu;
qu.push(root);
while(!qu.empty()){
Node* tmp = qu.front();
qu.pop();
if(tmp->val == m) return ctr;
ctr++;
if(tmp->Left != NULL) qu.push(tmp->Left);
if(tmp->Right != NULL) qu.push(tmp->Right);
}
}
int main(void){
int n, m;
scanf("%d%d", &n, &m);
Node* root = GetNode(n);
Node* tmp;
queue<Node*> qu;
qu.push(root);
while(!qu.empty()){
tmp = qu.front();
qu.pop();
if(tmp->val == m) break;
tmp->Left = GetNode(2 * tmp->val);
qu.push(tmp->Left);
if(tmp->val-1 >= 0){
tmp->Right = GetNode(tmp->val - 1);
qu.push(tmp->Right);
}
}
printf("%d\n", BFS(root, m));
}
The while loop in your main() is an infinite loop. There are no conditions that will terminate that loop. Your program keeps allocating memory for the queue, until it runs out of space.
Your continue should be a break. Still, this while() loop is very inefficient, due to the exponentially-growing queue that it generates.
You need to store the level of the node (root level: 0) because this will give you the steps you need to get m.
struct Node{
int val;
Node* Left;
Node* Right;
int lev;
};
Then, getNode will have one more parameter(level):
Node* GetNode(int val,int l){
Node* newnode = new Node();
newnode->val = val;
newnode->lev = l;
newnode->Left = NULL;
newnode->Right = NULL;
return newnode;
}
The root of the tree starts with level 0:
Node* root = GetNode(n,0);
And when you want to get a new node the level will be the level of the parent +1:
node->Left = GetNode(value,(node->lev)+1);
Your break is not in the most efficient place, you should stop your loop when you add a new node (with value tmp->val*2 or tmp->val-1) and any of these are m (and dont forget to update tmp, you will use it to print the answer).
Another important thing to make your algorithm efficient is to know when does your node should be add in the tree. One of them is "if them is if tmp->val-1 is less or equal 0 (number must always be positive). Also, if the node is higher than m, then it shouldn't increase, so tmp->left is going to be created only if tmp->val < m.
Finally, if you reach a number that is already in your tree, then you should add that node (this validation is done with !nit.count(x) that means "if I dont have any x in my map").
//this if comes inmediatly after reading n and m
if (n==m){
cout<<0<<endl;
return 0;
}
while(!qu.empty()){
tmp = qu.front();
qu.pop();
if (!nit.count(2 * tmp->val) && (tmp->val<m)){
tmp->Left = GetNode(2 * tmp->val,tmp->lev+1);
//cout<<2 * tmp->val<<endl;
if ((2 * tmp->val)==m){
tmp=tmp->Left; break;
}
nit[2 * tmp->val]++;
qu.push(tmp->Left);
}
if(!nit.count(tmp->val-1) && (tmp->val-1 > 0)){
tmp->Right = GetNode(tmp->val - 1,tmp->lev+1);
//cout<<tmp->val-1<<endl;
if ((tmp->val-1)==m){
tmp=tmp->Right; break;
}
nit[tmp->val-1]++;
qu.push(tmp->Right);
}
}
Now you have the answer:
printf("%d\n",tmp->lev);
This is the entire code:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <queue>
using namespace std;
struct Node{
int val;
Node* Left;
Node* Right;
int lev;
};
Node* GetNode(int val,int l){
Node* newnode = new Node();
newnode->val = val;
newnode->lev = l;
newnode->Left = NULL;
newnode->Right = NULL;
return newnode;
}
int main(void){
int n, m;
map<int,int>nit;
scanf("%d%d", &n, &m);
if (n==m){
cout<<0<<endl;
return 0;
}
Node* root = GetNode(n,0);
nit[n++];
Node* tmp;
queue<Node*> qu;
qu.push(root);
while(!qu.empty()){
tmp = qu.front();
qu.pop();
if (!nit.count(2 * tmp->val) && (tmp->val<m)){
tmp->Left = GetNode(2 * tmp->val,tmp->lev+1);
//cout<<2 * tmp->val<<endl;
if ((2 * tmp->val)==m){
tmp=tmp->Left; break;
}
nit[2 * tmp->val]++;
qu.push(tmp->Left);
}
if(!nit.count(tmp->val-1) && (tmp->val-1 > 0)){
tmp->Right = GetNode(tmp->val - 1,tmp->lev+1);
//cout<<tmp->val-1<<endl;
if ((tmp->val-1)==m){
tmp=tmp->Right; break;
}
nit[tmp->val-1]++;
qu.push(tmp->Right);
}
}
printf("%d\n",tmp->lev);
}
Sorry for my English c:
I was reading about Quicksort, and most of the codes I found were extremely complicated. So, I decided to make one on my own, wherein I considered the first element as pivot and then calling sort function recursively on the rest of the list.
I made the following code for Quicksort. It's as follows:
#include <iostream>
using namespace std;
class node
{
public:
int data;
node * next;
};
node * newnode (int x);
void quicksort(node ** begin, node ** end);
int main (void)
{
int foo,n,i,j,k;
node * temp;
node * head = NULL;
node * tail = NULL;
cout<<"How many nodes do you want to insert\n";
cin>>n;
cout<<"Enter data of linked list\n";
for ( i = 0; i < n; i++ )
{
cin>>foo;
node * bar;
if (head == NULL)
{
head = newnode(foo);
tail = head;
}
else
{
bar = newnode(foo);
tail->next = bar;
tail = bar;
}
}
cout<<"The linkedlist that you entered is as follows\n"; // Taking input
temp = head;
node * prev = NULL;
while (temp != NULL)
{
cout<<temp->data<<"\t";
prev = temp;
temp = temp->next;
}
cout<<"\n";
cout<<"Sorting the linked list now\n"; // Calling sort function
quicksort(&head,&prev);
temp = head;
while (temp != NULL) // Printing output
{
cout<<temp->data<<"\t";
temp = temp->next;
}
return 0;
}
node * newnode (int x) // for allocating a new node
{
node * foo = new node;
foo->data = x;
foo->next = NULL;
return foo;
}
void quicksort(node ** begin, node ** end) // actual sort function
{
if (*begin == *end)
return;
node * pivot = *begin;
node * temp = *begin;
temp = temp->next; // for pointing to next element
while (temp != *end)
{
if (temp->data < pivot->data)
{
node * temp1 = *begin; // swapping the two nodes if less than pivot
*begin = temp;
temp = temp->next;
(*begin)->next = temp1;
}
else
temp = temp->next; else moving to next
}
quicksort(begin,&pivot); // calling for remaining elements (first half)
quicksort(&(pivot->next),end); for second half
}
Howeever, when I run this, on input as 5 4 3 2 1, it sort of goes into an infinite loop. I tried running it through a debugger, but it get's extremely complicated to the extent that I lose my way in between. Can you point out the error where I might be going wrong? Thanks!
I'm fairly bad at coding so I really need some help as this homework is dued by Wednesday. I have seen mergesort normally split into three functions: (mergesort, sortedmerge, frontbacksplit, etc). But my professor's array based mergesort is done in one function so I'm assuming he wants us to only use one function as well for this linked list... (unless it is possible to implement a function within a function?) We have to write the function "struct listnode * mergesort(struct listnode *data)" and submit it to him. What I have done so far (I think) is splitting the linked list into 2 sub linked list but now I don't know how to "recursively" sort them.. Professor told us to write the function in C or C++, but the test code he provided us below is in C.
#include <stdio.h>
#include <stdlib.h>
struct listnode { struct listnode * next;
long value; } ;
//This is the function I need to write:
struct listnode * mergesort(struct listnode *data)
{ int temp, finished = 0;
struct listnode *i, *j, *tail, *head, *ahead, *bhead, *atail, *btail;
if ( a == NULL )
return;
head = data;
tail = head->next;
ahead = head;
bhead = tail;
i = ahead;
j = bhead;
tail = tail->next;
while ( tail !=NULL ) {
atail = tail;
i->next = atail;
i = i->next;
tail = tail->next;
btail = tail;
j->next = btail;
j = j->next;
tail = tail->next;
}
};
//Testing code provided by professor:
int main(void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc( 500000*sizeof(struct listnode));
for( i=0; i< 500000; i++ )
{ (space + i)->value = 2*((17*i)%500000);
(space + i)->next = space + (i+1);
}
(space+499999)->next = NULL;
node = space;
printf("\n prepared list, now starting sort\n");
node = mergesort(node);
printf("\n checking sorted list\n");
for( i=0; i < 500000; i++)
{ if( node == NULL )
{ printf("List ended early\n"); exit(0);
}
if( node->value != 2*i )
{ printf("Node contains wrong value\n"); exit(0);
}
node = node->next;
}
printf("Sort successful\n");
exit(0);
}
The general approach:
if( list contains 0 or 1 item)
return the list; // it is already sorted
split the list into halves;
mergesort( first part);
mergesort( second part);
merge sorted parts;
return the merged list;
A list contains 0 or 1 item condition:
head == NULL || head->next == NULL
To split the list, you need to find its middle:
ahead = atail = head; // first item
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
atail = atail->next;
btail = btail->next;
if( btail->next)
btail = btail->next;
}
bhead = atail->next; // disconnect the parts
atail->next = NULL;
To merge two sorted lists:
if(ahead->value <= bhead->value) // set the head of resulting list
head = tail = ahead, ahead = ahead->next;
else
head = tail = bhead, bhead = bhead->next;
while(ahead && bhead)
if(ahead->value <= bhead->value) // append the next item
tail = tail->next = ahead, ahead = ahead->next;
else
tail = tail->next = bhead, bhead = bhead->next;
if(ahead) // once one part got exhausted append the remaining other part
tail->next = ahead;
else
tail->next = bhead;
I am new to linked list this is my second problem after inserting element in LL.Now i am trying to insert element at nth position.
I do so like this:
(1) First taking the size of user at terminal.
(2) Second read the input continuously from the user until the size.
(3) I add the element read at terminal at the beginning of the LL.
(4) I print that LL until formed.
Until here everything works fine
(5) Now after that i try to do addition at nth position in LL but it give 3 errors That i have explained in comments in my code. Also please tell me if my logic to add the element at nth position is correct or not ?
Note: I am obliged to pass the List node as a reference only in function call (and the dereference them inside function definition)
Below is my full code pointing errors in comments.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct node
{
int freq;
struct node * next;
};
typedef struct node node;
///////////////////////////// Function definitions ////////////////////////////////////////
insert_beginning(int size, node * * head)
{
node * temp;
temp = (node * ) malloc(sizeof(node));
temp -> freq = size;
temp -> next = * head;
* head = temp;
}
insert_Nth_position(int posn, int varn, node * * head)
{
int count = 0;
do
{
* head = * head -> next;//The first error is here , "next is something not structure or union"
count++;
} while (count != posn - 1); //this loop i do to go to node at nth position
node * temp2 = * head;
temp2 = (node * ) malloc(sizeof(node));
temp2 -> freq = varn;
temp2 -> next = * head -> next; //The seond error is here , "next is something not structure or union"
* head -> next = temp2;//The third error is here , "next is something not structure or union"
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
main()
{
int size, data, i, pos,
var;
node * head = NULL;
printf("enter the size of node\n");
scanf("%d", & size);
printf("start entering the number of elements until your size\n");
for (i = 1; i <= size; i++)
{
scanf("%d", & data);
insert_beginning(data, & head);
}
node * temp1;
temp1 = head;
while (temp1 != NULL)
{
printf("%d-> ", temp1 -> freq);
temp1 = temp1 -> next;
}
printf("enter the posotion where to add the node\n");
scanf("%d", & pos);
printf("enter the variable node\n");
scanf("%d", &var);
insert_Nth_position(pos,var, & head); //There may be problem here
printf("Print after addition\n");
node * temp3 = head;
while (temp3 != NULL)
{
printf("%d-> ", temp3 -> freq);
temp3 = temp3 -> next;
}
}
The actual errors are :
hp#ubuntu:~/Desktop/Internship_Xav/Huf_pointer$ gcc tlt.c -o tlt
tlt.c: In function ‘insert_Nth_position’:
tlt.c:26:18: error: request for member ‘next’ in something not a structure or union
tlt.c:32:28: error: request for member ‘next’ in something not a structure or union
tlt.c:33:9: error: request for member ‘next’ in something not a structure or union
Answer is welcome in any language c/c++ or algorithm even.
* head = * head -> next;
Here, the arrow operator -> has a higher precedence than address-of operator *, you need parenthesis to make it compile:
*head = (*head)-> next;
First of all your functions have no return type. Though old C compilers allow to do this defining implicitly the return type as int I advice to specify explicitly the return type of a function.
As for your errors then you shall not use the dereference operator in expressions as you do
* head = * head -> next;
or
* head -> next = temp2;
It would be correct to write
*head = ( *head )->next;
and
(*head )->next = temp2;
Though semantically this code is invalid. You are changing head in the loop while it shall not be changed.
Also function insert_Nth_position is wrong. Imagine for example that the value of parameter int posn is equal to 0. In this case condition while (count != posn - 1); will be invalid.
I would define the parameter that specifiers the position in the list as having type unsigned int or size_t
Function insert_Nth_position could look the following way
int insert_Nth_position( node ** head, size_t posn, int varn )
{
if ( posn == 0 ) return insert_beginning( head, varn );
node *tmp = *head;
while ( --posn && tmp ) tmp = tmp->next;
if ( tmp )
{
node *new_node = malloc( sizeof( node ) );
new_node->freq = varn;
new_node->next = tmp->next;
tmp->next = new_node;
}
return ( temp != NULL );
}
If your compiler supports C99 then the return type could be substituted for _Bool
Also function insert_beginning I would declare as
int insert_beginning( node ** head, int varn );
I'm trying to write a function that sums integers, each of which are represented by a linked list where each node->data is a digit 0-9. The least significant digit is at the head of the list and the most is at the tail.
This is from the book Cracking the Coding Interview. Here is my code:
SinglyLinked<int>& addLists(SinglyLinked<int>& ll1, SinglyLinked<int>& ll2)
{
SinglyLinked<int> *sumList = new SinglyLinked<int>;
ListNode<int> *node1 = ll1.head; ListNode<int> *node2 = ll2.head;
int sum, carry = 0;
while(node1 || node2)
{
if(node1)
sum += node1->data;
if(node2)
sum += node2->data;
sum += carry;
carry = 0;
sumList->insertAtEnd(sum%10);
if(sum > 9)
carry = 1;
sum = 0;
node1 = node1->next; node2 = node2->next;
}
return *sumList;
}
First of all, is this code correct? It seems to work, but it seg faults when given two linked lists (integers) of different lengths. I'm wondering if the problem was only intended to solve for the case where the integers are of the same length. If not, how would I go about summing two lists of different lengths? My naive solution is to store the length of each list and then use that to create the digits which only one of the numbers will contribute to, until the two integers are aligned. Is there something more elegant than that?
It segfaults on different length lists, because then the node1 or node2 points to null.
Change
node1 = node1->next; node2 = node2->next;
to
if (node1)
node1 = node1->next;
if (node2)
node2 = node2->next;
while(node1 || node2)
If either node is ok keep going. But the block expects both nodes to be valid when it gets here:
node1 = node1->next; node2 = node2->next;
You needs your "nexts" in the if node1 checks:
if(node1) {
sum += node1->data;
node1 = node1->next;
}
etc.
There is one condition, where node1 and node2 will point to NULL and if there is a carry from the previous digit operation, it will not be appended to the end of the sumlist. For example, 6->5->4 + 4->5->6 should be 0->1->1->1 but sumlist will be 0->1->1. So before return line you should add:
if (carry)
sumList->insertAtEnd(carry);
Another solution to this problem is when you add the numbers in each list, add them together to get the big sum equal to the sum of two lists, convert that sum into a string, and append each character of the string to a new list. Hope it helps someone. Below is the code.
node.h file
#ifndef node_h
#define node_h
class LinkedList
{
private:
struct node
{
int data;
node *next;
};
node *head;
public:
LinkedList ();
node *createNode (int key);
void appendNodeBack (const int &key);
void printList ();
int SumOfNodes (const LinkedList list1);
};
#endif
node.cpp file
#include "node.h"
#include <math.h>
LinkedList::LinkedList ():head(NULL) {}
LinkedList::node *LinkedList::createNode (int key)
{
node *newNode = new node;
newNode->data = key;
newNode->next = NULL;
return newNode;
}
void LinkedList::appendNodeBack (const int &key)
{
node *newNode = createNode (key);
//if tree is empty
if (head == NULL)
{
head = newNode;
return;
}
//if tree is not empty
//traverse to the last node in the list
node *temp = head;
while (temp->next != NULL)
temp = temp->next;
temp->next = newNode;
}
void LinkedList::printList ()
{
//if tree is empty
if (head == NULL)
{
std::cout << "Tree is empty!\n";
return;
}
//if tree not empty
node *temp = head;
while (temp != NULL)
{
std::cout << temp->data<<"-->";
temp = temp->next;
}
std::cout << "NULL\n";
}
int LinkedList::SumOfNodes (const LinkedList list1)
{
//find the length of the list
node *temp = head;
int count = 0;
while (temp != NULL)
{
count++;
temp = temp->next;
}
//re-assign temp to head
temp = head;
//calculate the sum
unsigned int sum = 0;
for (unsigned int i = 1; i < pow (10, count); i = i * 10)
{
sum = sum + temp->data * i;
temp = temp->next;
}
return sum;
}
main.cpp file
#include <iostream>
#include "node.cpp"
int main ()
{
LinkedList list1, list2, list3;
list1.appendNodeBack (2);
list1.appendNodeBack (3);
list1.appendNodeBack (5);
list1.appendNodeBack (4);
list2.appendNodeBack (5);
list2.appendNodeBack (6);
list2.appendNodeBack (7);
list2.appendNodeBack (8);
list1.printList ();
std::cout << list1.SumOfNodes (list1) << std::endl;
list2.printList ();
std::cout << list2.SumOfNodes (list2) << std::endl;
unsigned int sum = list1.SumOfNodes (list1) + list2.SumOfNodes (list2);
//convert the number to string
std::string str = std::to_string (sum);
//append integer value to the new list
for (unsigned int i = 0; i < str.length (); i++)
list3.appendNodeBack (int (str[i] - '0'));
std::cout << "The new list becomes\n";
list3.printList();
return 0;
}