Remove max value from simply-connected list - c++

How can I can remove max value from a Simply-Connected list?
Two of the solutions I tried produce wrong results. Please explain to me what am I doing wrong. With code, if not difficult.
Stack:
struct Stack
{
int info;
Stack *next;
} *top;
Wrong solution 1:
void delMaxValue(Stack **stck, int maxValue){
Stack *tmp = NULL;
do {
if ((*stck)->info != maxValue)
tmp = *stck;
cout << tmp->info << endl;
tmp = tmp->next;
*stck = (*stck)->next;
} while ((*stck)->next != NULL);
while (tmp != NULL)
{
*stck = tmp;
*stck = (*stck)->next;
tmp = tmp->next;
}
Wrong solution 2:
Stack* deleteMaxValue(Stack *begin) {
Stack *t = begin, *p = begin->next;
for (; p; p = p->next)
if (p->info > t->info) t = p;
p = begin;
if (p != t) {
while (p->next != t) p = p->next;
p->next = t->next;
}
else
begin = t->next;
delete t;
return begin;}

#include <cstdio>
#include <iostream>
struct Stack
{
int info;
Stack *next;
// added just to easy initialization
Stack(int _info, Stack *_next) : info(_info), next(_next) {}
} *top;
void delMaxValue(Stack *&head)
{
// first - find MaxValue in the list
// as you can see, i save pointer to the previous element in the list
Stack* max_prev = nullptr;
Stack* max = head;
for(Stack *i_prev = nullptr, *i = head; i; i_prev = i, i = i->next) {
if (max->info < i->info) {
max_prev = i_prev;
max = i;
}
}
// max has the maximum value and max_prev is the element before max in the list
// now we remove max
if (max_prev == nullptr) {
// max has no prev, so max is the head of the list. We assign the new head
head = max->next;
} else {
max_prev->next = max->next;
max->next = NULL;
}
}
void printStack(Stack *head) {
std::cout << "Priting " << head << std::endl;
for(Stack *i = head; i; i = i->next) {
std::cout << i << " " << i->info << std::endl;
}
}
int main()
{
Stack *head = new Stack(1, new Stack(15, new Stack(10, nullptr)));
printStack(head);
delMaxValue(head);
printStack(head);
return 0;
}
You may interest yourself in list helping macros from bsd, now available in glibc, newlib, openbsd etc., see here.

Your first solution takes maximum value as a parameter, while the second one doesn't. I am assuming we don't have the maximum value and will calculate it while processing the stack.
The basic approach should be to think of a logic first.
Step 1.) We need to pop all the elements to find the maximum element in the stack. Also, we need to store all the values we popped in another stack(say, auxiliary). Now, we are aware of the maximum value(say MAX).
Step 2.) Note we would have the stack in reverse now. Pop all elements from the auxiliary stack and if the value is not max, push them in the original stack.
Data Initially,
Original Stack: 1->2->3->4->100->5->7->NULL
Auxiliary Stack: NULL
Data after first Step,
Original Stack: NULL
Auxiliary Stack: 7->5->100->4->3->2->1->NULL
MAX: 100
Finally,
Original Stack: 1->2->3->4->5->7->NULL
Auxiliary Stack: NULL
Try to code for this. Your both solutions are doing things way differently than expected.

I hope It will be helpful.
#include <iostream>
struct LList
{
int info;
LList *next;
//constructer
LList(int info_) :info(info_) {
next = nullptr;
}
};
void removeMaxValue(LList *&root) {
int max = 0;
LList *temp = root;
//Searching for max value
while (temp!=nullptr)
{
if (temp->info > max)
max = temp->info;
temp = temp->next;
}
temp = root;
//Find max value and remove
while (temp->next->info != max)
temp = temp->next;
LList *maxNode = temp->next;
temp->next = temp->next->next;
delete maxNode;
}
void print(const LList *root)
{
while (root!=nullptr)
{
std::cout << root->info << " ";
root = root->next;
}
std::cout << std::endl;
}
int main() {
LList *root = new LList(15);
root->next= new LList(10);
root->next->next= new LList(45);
root->next->next->next = new LList(85);
root->next->next->next->next = new LList(5);
//before removing
print(root);
removeMaxValue(root);
//After removing
print(root);
std::cin.get();
}

Your two functions take two different approaches. I chose the one where the function doesn't know what actual max value is so it has to find it first.
First, the function just iterates through the elements and chooses the max value.
Then it searches for the first node that contains this value and removes the node.
void stackRemoveMaxValue(Stack*& top) {
if(top == nullptr) {
return;
}
// Find max value.
int maxValue = top->info;
Stack* node = top->next;
for(; node != nullptr; node = node->next) {
if(maxValue < node->info) {
maxValue = node->info;
}
}
// Remove first node that contains maxValue.
Stack* previous = nullptr;
Stack* current = top;
do {
if(current->info != maxValue) {
previous = current;
current = current->next;
} else {
if(previous != nullptr) {
previous->next = current->next;
} else {
top = current->next;
}
delete current;
return;
}
} while(current != nullptr);
}

Related

Freeing memory space when deleting a node in a circular LinkedList without declaring a new pointer

I've come across a problem in dynamic programming in which we are asked to delete nodes of a circular LinkedList, in the following manner.
Delete the first node then skip one and delete the next, then skip two and delete the next, then skip three and delete the next and it continues until we are left with only one node, and that one node is our answer.
For example, if we have 5 nodes, then the nodes will be deleted in the following order – 1 3
2 5 4, and the last node would be 4.
Similarly, if we have 4 nodes, then the nodes will be deleted in the following order – 1 3 4
2, and the last node would be 2.
This is a screenshot of the part of the code that requires improvement
using this code in c++, I've been successful in solving the problem but I want to free the memory using delete command as I delink a node. Can anyone please help me to solve this problem by improving this code (while using minimal memory)?
The node can be deleted by declaring another pointer, but that would only increase the memory usage, which I don't want at the moment.
The entire code is given below
#include<iostream>
using namespace std;
class linked {
public:
int x;
linked* next;
//methods
linked(int p); //constructor
static void insert(linked*& head, int p);//method to insert new node
static int print(linked* head);//method to print the result
static void del(linked*head, int size) {//method to delete all the undesired nodes
linked* temp = head;
while (temp->next != head) {//traversing until we find the node just behind the node we want to del
temp = temp->next;
}
for(int i=1;i < size;i++) {
for (int k = 1; k < i; k++) {//del nodes with increment
temp = temp->next;
}
temp->next = temp->next->next; //delinking the
}
}
};
int main() {
int no_of_nodes;
cout << "enter the number of nodes you want to have" << endl;
cin >> no_of_nodes;
linked* head = new linked(1);
for (int i = 1; i <= no_of_nodes; i++) {
linked::insert(head, i);//for inserting nodes, as desired by the user
}
linked::del(head, no_of_nodes);
cout<< linked::print(head);
}
linked::linked(int p) {
x = p;
next = NULL;
}
void linked::insert(linked*& head, int p) {
linked* temp = head;
linked* n = new linked(p);//for the new node
if (p == 1) {
head->next = head;
return;
}
while (temp->next != head) {
temp = temp->next;
}
temp->next = n;
n->next = head;
}
int linked::print(linked* head) {
linked* temp = head;
for (int i = 0; i < 25; i++) {//this can go longer(or shorter), i limited it to 25 only, just to ensure that it is a circular linked list
temp = temp->next;
if (temp == temp->next) {
return temp->x;
}
}
cout << endl;
}
P.S. The problem was taken from ICPC Asia Topi 2022, link: (https://giki.edu.pk/wp-content/uploads/2022/03/ICPC_Day_2.pdf)
It seems neither professional programmer are going to help you.:)
So we, beginners, should help each other.:)
You should declare a class of the circular singly-linked list with non-static member functions.
As for the task to remove all elements from the circular singly-linked list except one using the described algorithm then I can suggest the following approach.
At first within the function remove the cycling. This will make easy to remove elements from the circular singly-linked list.
After all elements except one will be removed then restore the cycling.
Here is a demonstration program.
#include <iostream>
#include <utility>
#include <stdexcept>
class CircularList
{
private:
struct Node
{
int data;
Node *next;
} *head = nullptr;
public:
CircularList() = default;
CircularList( const CircularList & ) = delete;
CircularList &operator =( const CircularList & ) = delete;
~CircularList()
{
clear();
}
void clear()
{
if (head)
{
Node *current = head;
do
{
delete std::exchange( current, current->next );
} while (current != head);
head = nullptr;
}
}
void insert( int data )
{
Node *new_node = new Node{ data };
if (not head)
{
new_node->next = new_node;
head = new_node;
}
else
{
Node *current = head;
while (current->next != head) current = current->next;
new_node->next = head;
current->next = new_node;
}
}
const int & top() const
{
if (not head)
{
throw std::out_of_range( "Error. The list is empty." );
}
return head->data;
}
void remove_except_one()
{
if (head)
{
Node *last = head;
while (last->next != head) last = last->next;
last->next = nullptr;
Node **current = &head;
for (size_t n = 0; head->next != nullptr; ++n)
{
for (size_t i = 0; i != n; i++)
{
current = &( *current )->next;
if (*current == NULL) current = &head;
}
Node *tmp = *current;
// The statement below is uncommented for the debug pyrpose.
std::cout << ( *current )->data << '\n';
*current = ( *current )->next;
if (*current == nullptr) current = &head;
delete tmp;
}
head->next = head;
}
}
friend std::ostream &operator <<( std::ostream &os, const CircularList &list )
{
if (list.head)
{
const Node *current = list.head;
do
{
os << current->data << " -> ";
current = current->next;
} while (current != list.head);
}
return os << "null";
}
};
int main()
{
CircularList list;
for (int i = 0; i < 5; i++)
{
list.insert( i + 1 );
}
std::cout << "The list: ";
std::cout << list << '\n';
list.remove_except_one();
std::cout << "The list: ";
std::cout << list << '\n';
list.clear();
std::cout << '\n';
for (int i = 0; i < 4; i++)
{
list.insert( i + 1 );
}
std::cout << "The list: ";
std::cout << list << '\n';
list.remove_except_one();
std::cout << "The list: ";
std::cout << list << '\n';
}
The program output is
The list: 1 -> 2 -> 3 -> 4 -> 5 -> null
1
3
2
5
The list: 4 -> null
The list: 1 -> 2 -> 3 -> 4 -> null
1
3
4
The list: 2 -> null
Within the function remove_except_one this statement
std::cout << ( *current )->data << '\n';
is present for the debug purpose only. You may remove or comment it if you want.
There are some problems with your code:
1) empty list should be nullptr
In main:
linked* head = new linked(1);
should be
linked* head = nullptr;
You start with an empty list. You do not know what data you will insert first and you assume the first value inserted will be 1. With this change you also have to change your insert:
if (p == 1) {
has to check
if (head == nullptr) {
2) replace head with tail
In a circular single linked list you always need the previous node to delete a node or to insert at the head. That means you have to traverse the whole list when given the head to find the previous. This is rather slow, so store the tail of the list instead. Then the head is tail->next and you can delete the head or insert at the head directly.
3) del breaks head
static void del(linked*head, int size) {
If this deletes the first node in the list then the head the caller passed in becomes a dangling pointer. There is no way to update the pointer the caller holds for the list. Just like with insert you need to pass in a reference:
static void del(linked*&head, int size) {
Now for your problem of how to delete the node without extra memory:
You can't. You always need extra memory to temporarily store the node to be deleted while you fix up the links in the list and then delete it. You already needed that extra memory to find the tail of the list and you called it temp.
static void del(linked*&tail) {
if (tail == nullptr) return; // no list, nothing to delete
for (std::size_t skip = 0; tail->next != tail; ++skip) { // keep going till only one node is left
for(std::size_t i = 0; i < skip; ++i) tail = tail->next; // skip nodes
// delete node
linked* temp = tail->next;
tail->next = tail->next->next;
delete temp;
}
}

Why is there an access violation error when trying to access reference pointer?

I'm trying to make single linked list's fucntions.
but it reports an error. like this..
i am trying to a lot of thing about that.
like using rvlaue reference, double pointer
but nothings work..
what is the problem?
and can i return p pointer in getNode(int k) fucntion?
#include<iostream>
using namespace std;
template<typename T>
class SingleLList {
private:
template<typename T>
struct Node {
T data;
Node<T>* next;
};
Node<T>* head;
int size; // for List size
public:
SingleLList() :head(nullptr) {};
~SingleLList() {
Node<T>* delNode;
while (head->next != nullptr) {
delNode = head;
head = head->next;
delete delNode;
}
};
// add Node at index th
void addNode(int index, T data) {
if (index < 0)return;
Node<T>* newNode = new Node<T>;
newNode->data = data;
newNode->next = nullptr;
if (index == 0) { // add at 0
// empty
if (head == nullptr) head = newNode;
// not empty
else {
newNode->next = head->next;
head = newNode;
}
size++;
}
else {
Node<T>* prev = head;
for (int i = 1; i < index && prev != nullptr; i++) {
prev = prev->next;
}
newNode->next = prev->next;
prev->next = newNode;
size++;
}
}
// traversa
void showList()const {
Node<T>* p = head;
cout << "Single Linked List : [ ";
while (p != nullptr) {
cout << p->data << " ";
p = p->next;
}
cout << " ]" << "total elements are : "
<< size << endl;
}
// return k th Node by reference.
Node<T>*& getNode(int k)const {
if (head == nullptr || k > size) {
Node<T>* temp = nullptr;
return temp;
}
// Node<T>* p; < -- is it okay?
Node<T>* p = new Node<T>;
p= head;
for (int i = 1; i < k && p->next != nullptr; i++) {
p = p->next;
}
cout << " address of p : " << &p << endl;
cout << "value of p : " << p << endl;
return p;
}
// delete n Node in list
void deleteNode(Node<T>*& n) {
cout << "address of n : " << &n << endl;
cout << n->data << endl;
if (n->next == nullptr) { // if last node
delete n->next;
n = nullptr; //
size--;
}
else {
Node<T>* del_node = n->next;
n->data = n->next->data;
n->next = n->next->next;
delete del_node;
size--;
}
}
};
int main() {
SingleLList<int> sll;
sll.addNode(0, 4);
sll.addNode(1, 5);
sll.addNode(2, 6);
sll.addNode(3, 8);
sll.addNode(4, 9);
sll.showList();
sll.deleteNode(sll.getNode(5));
sll.showList();
return 0;
}
and in main i make Linked List like this.
Node<T>*& getNode(int k)const {
if (head == nullptr || k > size) {
Node<T>* temp = nullptr;
return temp;
This same basic bug occurs several times in the shown code. All instances of this bug will need to be fixed.
temp is a local variable. Once this function returns, it goes out of scope and gets destroyed.
However: this function is declared as returning a reference to a pointer, and by returning temp this ends up returning a reference to an object that's already destroyed, when the function returns. All subsequent use of this reference automatically becomes undefined behavior, and the likely reason for your crash. For example:
sll.deleteNode(sll.getNode(5));
For example, getNode() returns a reference here. To add insult to injury this reference isn't even used immediately, but it gets passed to deleteNode(). By that time temp, or a reference to whatever was originally returned from getNode, is a distant memory and was already destroyed a long, long time ago, and attempting to reference it will not end well.
There are likely other issues, but this is fundamental, and fixing it will require fundamental changes to the shown logic, as such the first order of business will be to redesign the shown code, and it will likely involve other major changes to the rest of the code, as well.

Wrong Output while Printing maximum in linked list

I was printing the max of a linked list in C++ language . But I was not getting the desired output. While Building and running the code, the terminal gets stuck in building it. I tried it in VS Code and Sublime text both. I am using mingw64 compiler.
After the run the program this happens Gets stuck after displaying the linked list
#include <stdlib.h>
#include <stdio.h>
using namespace std;
struct node {
int data;
struct node *next;
} *first = NULL;
//declaring a global head/first pointer which stores the address of first node
void create(int a[], int n) {
int i;
struct node *t, *last;
first = (struct node *)malloc(sizeof(struct node));
first->data = a[0];
first->next = NULL;
last = first;
for (i = 1; i < n; i++) {
// t = new node;
t = (struct node *)malloc(sizeof(struct node));
t->data = a[i];
t->next = NULL;
last->next = t;
last = t;
}
}
void display(struct node *p) {
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
}
int Max(struct node *p) {
int max = -100;
while (p != NULL) {
if (p->data > max) {
max = p->data;
p = p->next;
}
}
return max;
}
int main() {
int m = 0;
int a[] = { 3, 5, 7, 10, 15, 8, 12, 20 };
create(a, 8);
display(first);
printf("\n");
m = Max(first);
cout << "The maximum of the linked list is : " << m;
return 0;
}
while (p != NULL)
{
if (p->data > max)
{
max = p->data;
p = p->next;
}
}
Update this to
while (p != NULL)
{
if (p->data > max)
{
max = p->data;
}
p = p->next;
}
Otherwise your code will STUCK in infinite loop.
I usually prefer one line comparison so that code is easy to understand and no bus will appear
int Max(struct node *p) {
int max_number = INT_MIN;
while (p != NULL) {
max_number = max(max_number, p->data);
p = p->next;
}
return max_number;
}
Your code is a mixture of C and C++ code. You should settle for one or the other and use idioms appropriate for the one you choose. Using a mixture of C and C++ is a recipe for failure. As coded, the program is closer to C than C++, just remove the C++isms and program in C.
The reason it gets stuck is p does not get updated in the while loop when the value p->data is not greater than max. Note however that there are other problems: the code will not find the maximum value if all values are less than -100 and it will return -100 if the list is empty.
Here is a modified version, in C, with both issues corrected:
#include <stdio.h>
#include <stdlib.h>
//declaring a global head/first pointer which stores the address of first node
struct node {
int data;
struct node *next;
} *first = NULL;
/* append the elements from a[] to the end of the linked list */
void create(const int a[], int n) {
struct node *last;
last = first;
while (last && last->next) {
last = last->next;
}
for (int i = 0; i < n; i++) {
// t = new node;
struct node *t = (struct node *)malloc(sizeof(struct node));
if (t == NULL)
return;
t->data = a[i];
t->next = NULL;
if (last)
last->next = t;
else
first = t;
last = t;
}
}
void display(const struct node *p) {
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int getmax(struct node *p) {
int max = 0;
if (p != NULL) {
max = p->data;
p = p->next;
while (p != NULL) {
if (max < p->data) {
max = p->data;
}
p = p->next;
}
}
return max;
}
int main() {
int a[] = { 3, 5, 7, 10, 15, 8, 12, 20 };
create(a, sizeof(a) / sizeof(a[0]));
display(first);
printf("The maximum of the linked list is: %d\n", getmax(first));
return 0;
}
Except these two lines
using namespace std;
and
cout << "The maximum of the linked list is : " << m;
there is nothing in the program that could be referenced as a C++ code and not C code. Moreover you even forgot to include the header <iostream>.
Also the program has an inconsistence interface. Some functions deal directly with the global variable first while other functions accept the variable through parameters.
Even the function create can invoke undefined behavior because the user can pass as the second argument zero or a negative number.
void create(int a[], int n) {
int i;
struct node *t, *last;
first = (struct node *)malloc(sizeof(struct node));
first->data = a[0];
//...
In this case the expression a[0] has an indeterminate value.
The function Max (Why does its name start with an upper case letter?) has a bug. Moving to a next node occurs only in case when p->data > max
if (p->data > max) {
max = p->data;
p = p->next;
}
You need to place the statement
p = p->next;
after the if statement
int Max(struct node *p) {
int max = -100;
while (p != NULL) {
if (p->data > max) {
max = p->data;
}
p = p->next;
}
return max;
}
But in any case the function does not make a great sense because the returned value -100 for an empty list can be a valid data for the list.
If you are learning C++ then start to learn it from the C++ 17 Standard and use features of C++ instead of features of C as the C++ operator new instead of the C function malloc.
Your program as indeed a C++ program can look for example the following way.
#include <iostream>
#include <optional>
#include <functional>
#include <iterator>
struct node
{
int data;
node *next;
};
void clear( node * &head )
{
while ( head ) delete std::exchange( head, head->next );
}
void create( node *&head, const int a[], size_t n )
{
clear( head );
node **current = &head;
for (size_t i = 0; i < n; i++)
{
*current = new node{ a[i], nullptr };
current = &( *current )->next;
}
}
std::ostream &display( const node *head, std::ostream &os = std::cout )
{
for (const node *current = head; current; current = current->next)
{
os << current->data << " -> ";
}
return os << "null";
}
std::optional<int> max( const node *head )
{
std::optional<int> max_value;
if (head)
{
max_value = head->data;
for (const node *current = head->next; current; current = current->next)
{
if (max_value < current->data) max_value = current->data;
}
}
return max_value;
}
int main()
{
node *head = nullptr;
int a[] = { 3, 5, 7, 10, 15, 8, 12, 20 };
create( head, a, std::size( a ) );
display( head ) << '\n';
auto max_value = max( head );
if ( max_value )
{
std::cout << "The maximum of the linked list is : " << *max_value << '\n';
}
else
{
std::cout << "The list is empty.\n";
}
clear( head );
max_value = max( head );
if ( max_value )
{
std::cout << "The maximum of the linked list is : " << *max_value << '\n';
}
else
{
std::cout << "The list is empty.\n";
}
return 0;
}
The program output is
3 -> 5 -> 7 -> 10 -> 15 -> 8 -> 12 -> 20 -> null
The maximum of the linked list is : 20
The list is empty.

Passing by Pointer Issue

I'm trying to implement my own version of a linked list for learning. I have the following code. The reverseList function works correctly and if I print it inside that function it is good.
However, when I leave the function and then call the print method I get the the first value and then nothing (null). I'm guessing when I get out of the function it brings me back to the original first ([99]) element which is now actually the last element. So my print method outputs the element sees null is the next and ends.
Or I was thinking the changes I was making in the function were somehow only in that function's scope even though I passed a pointer, but that doesn't make sense because if that's the case then I should have all the original data still.
struct ListNode
{
int value;
ListNode* next = NULL;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
list = cur;
std::cout << cur->value << " list:" << list->value << std::endl;
}
void testLinkedList()
{
srand(time(NULL));
ListNode nodes;
nodes.value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(&nodes, i);
//insertList(&nodes, val);
}
printList(&nodes);
reverseList(&nodes);
printList(&nodes);
}
int main()
{
testLinkedList();
return 0;
}
Appreciative of any help you guys can give me,
Thanks!
Update:
By passing the ListNode *list to reverseList, you create a copy of your pointer which point to the same address with nodes. Inside the function, you assign list to the updated cur pointer but the copy will be destroyed at the end. list still points to the same address as before passing to reverseList but its next has changed.
I have modified your code a little bit:
#include <cstdlib>
#include <iostream>
struct ListNode
{
int value;
ListNode* next = nullptr;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == nullptr)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != nullptr)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode** list)
{
ListNode* cur = *list;
ListNode* next = cur->next;
ListNode* prev = nullptr;
while(cur != nullptr)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
*list = prev;
}
void cleanNodes(ListNode *list) {
// clean goes here
}
void testLinkedList()
{
srand(time(nullptr));
ListNode *nodes = new ListNode();
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
reverseList(&nodes);
printList(nodes);
cleanNodes(nodes);
}
int main()
{
testLinkedList();
return 0;
}
Try to compile with: -std=gnu++11
You don't change nodes in reverseList you're just changing list you're just changing a pointer on your struct which is a temporary object so physically nodes steel the same and pointed on the same first element which now has next attribute pointing on Null so the result of printList is correct. You need to work with pointers e.g.
#include <iostream>
#include <cstdlib>
struct ListNode
{
int value;
ListNode* next = NULL;
~ListNode(){
if(this->next)
delete this->next;
}
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
ListNode * reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
std::cout << cur->value << " list:" << list->value << std::endl;
return cur;
}
void testLinkedList()
{
srand(time(NULL));
ListNode * nodes = new ListNode;
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
nodes = reverseList(nodes);
printList(nodes);
delete nodes;
}
int main()
{
testLinkedList();
return 0;
}
Also, don't forget to delete object created dynamically
Reversing a linked list is not a fundamental operation. It does not belong among the basis operations of your class. It is easier (and safer) to implement it in terms of your other operations. Roughly:
Create an empty list.
While the first list is not empty, remove a node from the front of the first list and insert it into the front of the second list.
The second list is now the reverse of the original.

I have a program that works for whole numbers, but I need to get it to work for decimal numbers as well

So my assignment requires us to use doubly linked lists to add or multiply numbers together and print them out. I was able to get it to work for whole numbers, but I can't figure out what to change to make it work for decimal numbers as well. Here's what I've got so far. I know it's not the most efficient or cleanest code, but I can try to clarify stuff if it doesn't make sense to you
For example this program will work fine if I do 50382+9281 or 482891*29734,but I need to get it to work for something like 4.9171+49.2917 or 423.135*59
EDIT: Pretend the int values are doubles. I changed it on my actual code, but the result when I do the math is still giving me a whole number so I need to figure out how to insert the decimal at the right place
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
using namespace std;
// A recursive program to add two linked lists
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
// A linked List Node
struct node
{
int data;
node* next;
node *prev;
};
typedef struct node node;
class LinkedList{
// public member
public:
// constructor
LinkedList(){
int length = 0;
head = NULL; // set head to NULL
node *n = new node;
n->data = -1;
n->prev = NULL;
head = n;
tail = n;
}
// This prepends a new value at the beginning of the list
void addValue(int val){
node *n = new node(); // create new Node
n->data = val; // set value
n->prev = tail; // make the node point to the next node.
// head->next = n;
// head = n;
// tail->next = n; // If the list is empty, this is NULL, so the end of the list --> OK
tail = n; // last but not least, make the head point at the new node.
}
void PrintForward(){
node* temp = head;
while(temp->next != NULL){
cout << temp->data;
temp = temp->next;
}
cout << '\n';
}
void PrintReverse(){
node* temp = tail;
while(temp->prev != NULL){
cout << temp->data;
temp = temp->prev;
}
cout << '\n';
}
void PrintReverse(node* in){
node* temp = in;
if(temp->prev== NULL){
if(temp->data == -1)
cout << temp->data << '\n';
}
else{
cout << temp->data << '\n';
temp = temp->prev;
PrintReverse(temp);
}
}
// returns the first element in the list and deletes the Node.
// caution, no error-checking here!
int popValue(){
node *n = head;
int ret = n->data;
head = head->next;
delete n;
return ret;
}
void swapN(node** a, node**b){
node*t = *a;
*a = *b;
*b = t;
}
node *head;
node *tail;
// Node *n;
};
/* A utility function to insert a node at the beginning of linked list */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node = (struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* A utility function to print linked list */
void printList(struct node *node)
{
while (node != NULL)
{
printf("%d", node->data);
node = node->next;
}
// printf("\n");
}
// A utility function to swap two pointers
void swapPointer( node** a, node** b )
{
node* t = *a;
*a = *b;
*b = t;
}
/* A utility function to get size of linked list */
int getSize(struct node *node)
{
int size = 0;
while (node != NULL)
{
node = node->next;
size++;
}
return size;
}
// Adds two linked lists of same size represented by head1 and head2 and returns
// head of the resultant linked list. Carry is propagated while returning from
// the recursion
node* addSameSize(node* head1, node* head2, int* carry)
{
// Since the function assumes linked lists are of same size,
// check any of the two head pointers
if (head1 == NULL)
return NULL;
int sum;
// Allocate memory for sum node of current two nodes
node* result = (node *)malloc(sizeof(node));
// Recursively add remaining nodes and get the carry
result->next = addSameSize(head1->next, head2->next, carry);
// add digits of current nodes and propagated carry
sum = head1->data + head2->data + *carry;
*carry = sum / 10;
sum = sum % 10;
// Assigne the sum to current node of resultant list
result->data = sum;
return result;
}
// This function is called after the smaller list is added to the bigger
// lists's sublist of same size. Once the right sublist is added, the carry
// must be added toe left side of larger list to get the final result.
void addCarryToRemaining(node* head1, node* cur, int* carry, node** result)
{
int sum;
// If diff. number of nodes are not traversed, add carry
if (head1 != cur)
{
addCarryToRemaining(head1->next, cur, carry, result);
sum = head1->data + *carry;
*carry = sum/10;
sum %= 10;
// add this node to the front of the result
push(result, sum);
}
}
// The main function that adds two linked lists represented by head1 and head2.
// The sum of two lists is stored in a list referred by result
void addList(node* head1, node* head2, node** result)
{
node *cur;
// first list is empty
if (head1 == NULL)
{
*result = head2;
return;
}
// second list is empty
else if (head2 == NULL)
{
*result = head1;
return;
}
int size1 = getSize(head1);
int size2 = getSize(head2) ;
int carry = 0;
// Add same size lists
if (size1 == size2)
*result = addSameSize(head1, head2, &carry);
else
{
int diff = abs(size1 - size2);
// First list should always be larger than second list.
// If not, swap pointers
if (size1 < size2)
swapPointer(&head1, &head2);
// move diff. number of nodes in first list
for (cur = head1; diff--; cur = cur->next);
// get addition of same size lists
*result = addSameSize(cur, head2, &carry);
// get addition of remaining first list and carry
addCarryToRemaining(head1, cur, &carry, result);
}
// if some carry is still there, add a new node to the fron of
// the result list. e.g. 999 and 87
if (carry)
push(result, carry);
}
node* reverse_list(node *m)
{
node *next = NULL;
node *p = m;
node *prev;
while (p != NULL) {
prev = p->prev;
p->prev = next;
next = p;
p = prev;
}
return prev;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Multiply2(node* n1, node* n2);
int digitsPerNode = 2;
node* result;
node* resultp = result;
node* resultp2 = result;
void Multiply(node* n1, node* n2)
{
if (n2->prev != NULL)
{
Multiply(n1, n2->prev);
}
Multiply2(n1, n2);
resultp2 = resultp = resultp->prev;
}
void Multiply2(node* n1, node* n2)
{
if (n1->prev != NULL)
{
Multiply2(n1->prev, n2);
}
if (resultp2 == NULL)
{
resultp2->data = 0;
result = resultp = resultp2;
}
int m = n1->data * n2->data + resultp2->data;
int carryon = (int)(m / pow(10, digitsPerNode));
resultp2->data = m % (int)pow(10, digitsPerNode);
if (carryon > 0)
{
if (resultp2->prev == NULL)
{
resultp2->prev->data = carryon;
}
else
{
resultp2->prev->data += carryon;
}
}
resultp2 = resultp2->prev;
}
/* int* buffer;
int lenBuffer = 0;
void multiplyHelper(int v, node* , int o);
void addToBuffer(int v, int i);
node* multiply(node* num1, node* num2)
{
if (num1 == NULL || num2 == NULL) return NULL;
int length1 = getSize(num1);
int length2 = getSize(num2);
if (length1 > length2) return multiply(num2, num1);
// initialize buffer
lenBuffer = length1 + length2;
buffer = new int[lenBuffer];
memset(buffer, 0, sizeof(int) * lenBuffer);
// multiply
int offset = 0;
node* anode = num1;
while (anode && anode->data!= -1)
{
multiplyHelper(anode->data, num2, offset);
anode = anode->prev;
offset++;
}
// transfer buffer to a linked list
node* h;
int pos = 0;
while (pos < lenBuffer && buffer[pos] == 0) pos++;
if (pos < lenBuffer)
{
node* temp;
temp->data = buffer[pos++];
h = temp;
anode = h;
while (pos < lenBuffer)
{
node* temp;
temp->data = buffer[pos++];
anode->prev = temp;
anode = anode->prev;
}
}
delete buffer;
lenBuffer = 0;
buffer = NULL;
cout << h->data << endl;
return h;
}
// multiply a single digit with a number
// called by multiply()
void multiplyHelper(int value, node* head, int offset)
{
// assert(value >= 0 && value <= 9 && head != NULL);
if (value == 0) return;
node* anode = head;
int pos = 0;
while (anode != NULL)
{
int temp = value * anode->data;
int ones = temp % 10;
if (ones != 0) addToBuffer(ones, offset + pos + 1);
int tens = temp / 10;
if (tens != 0) addToBuffer(tens, offset + pos);
anode = anode->prev;
cout << anode->data;
pos++;
}
}
// add a single digit to the buffer at place of index
// called by multiplyHelper()
void addToBuffer(int value, int index)
{
// assert(value >= 0 && value <= 9);
while (value > 0 && index >= 0)
{
int temp = buffer[index] + value;
buffer[index] = temp % 10;
value = temp / 10;
index--;
}
}*/
// Driver program to test above functions
int main(int argc, char *argv[])
{
char filename[50];
string name= argv[1];
string dig;
name.erase(0,9);//Parse input to only get input file.
ifstream file;
int digits;
for(int i = 0; i < name.length(); i++){
if(name.at(i) == ';'){
// dig = name.substr(0,name.length()-i);
name = name.substr(0,name.length()-i);
}
}
//cout << dig << endl;
//file.open("input.txt");
file.open(name.c_str());
digits = 2;
///////
///////////////////////////////////////////////////////////////////////
int words = 0;
int numbers = 0;
while(!file.eof()) //Goes through whole file until no more entries to input
{
string word;
getline(file,word); //Inputs next element as a string
// word << file;
//cout << word << '\n';
int x = 0;
node *head1 = NULL, *head2 = NULL, *result = NULL;
int counter = 0;
int t1index = 0; //keep tracks of nodes to multiply
int t2index = 0;
char operatorX;
LinkedList tempList1;
LinkedList tempList2;
while(x<word.length()) //Loops through each string input
{
//if(x<word.length()&&isalpha(word.at(x))) //Checks that x is in bounds and that char at position x is a letter
if(x<word.length()&&isdigit(word.at(x))) //Checks that x is in bounds and that char at position x is a number/digit
{
int start = x;
while(x<word.length()&&isdigit(word.at(x))) //Loops past the number portion
{
x++;
}
string temp = word.substr(start, x).c_str();
// cout << temp << '\n';
for(int i = 0; i < temp.length();i++){
tempList1.addValue(atoi(temp.substr(i, 1).c_str()));
// push(&head1, atoi(temp.substr(i, 1).c_str()));
counter++;
t1index++;
}
//search for the operator
while(x<word.length()){
if(x<word.length()&& (!isspace(word.at(x)) && !isdigit(word.at(x))))
{
while(x<word.length()&&(!isspace(word.at(x)) && !isdigit(word.at(x)))) //Loops past the letter portion
{
// cout << (word.at(x))<< '\n';
operatorX = word.at(x);
x++;
}
//search second value
while(x<word.length()){ //second value find
//start
if(x<word.length()&&isdigit(word.at(x))) //Checks that x is in bounds and that char at position x is a number/digit
{
int start = x;
while(x<word.length()&&isdigit(word.at(x))) //Loops past the number portion
{
x++;
}
string temp = word.substr(start, x).c_str();
for(int i = 0; i < temp.length();i++){
tempList2.addValue(atoi(temp.substr(i, 1).c_str()));
// push(&head2, atoi(temp.substr(i, 1).c_str()));
// cout << atoi(temp.substr(i, 1).c_str());
counter++;
}
//////START READING NUMBERS BACKWARDS
LinkedList finalList;
node* tempA = tempList1.tail;
node* tempB = tempList2.tail;
// multiply(tempA, tempB);
//ADDITION
while(tempA != NULL){
if(tempA->data != -1){
push(&head1,tempA->data);
// cout << tempA->data;
}
tempA = tempA->prev;
}
while(tempB != NULL){
if(tempB->data != -1){
push(&head2, tempB->data);
// cout << tempB->data;
}
tempB = tempB->prev;
}
// multiply(head1, head2);
// result = multiply(head1, head2);
// tempList1.PrintReverse();
addList(head1, head2, &result);
printList(head1);
cout << operatorX;
printList(head2);
cout << "=";
printList(result);
cout << endl;
}
else{
x++;
}
//end
}
}
else{
x++;
}
}
}
else //If char at position x is neither number or letter skip over it
{
x++;
}
}
}
}
Since you're working in C++, use a template/overloaded operators. Cast your ints to a floating point type as necessary. See e.g.:
C++ Template problem adding two data types