so i want to implement a queue data structure in c++ and use some special methods like the delete_at() putting into consideration the constraints of the queue data structure, so I made it using the dequeue method and took all the data that are not equal to the index the user want to delete and stored in array in order to enqueue it all back in but without the index that the user want to delete, however nothing gets deleted , so here is the code :
#include <list>
using namespace std;
class Queue{
private:
struct node {
int data;
struct node *next;
};
struct node* front = NULL;
struct node* rear = NULL;
public:
void Enqueue(int d) {
struct node* tmp=new node;
if (rear == NULL) {
tmp->next = NULL;
tmp->data = d;
rear=tmp;
front = rear;
}
else {
rear->next = tmp;
tmp->data = d;
tmp->next = NULL;
rear = tmp;
}
}
int Dequeue() {
struct node* tmp = front;
int data=front->data;
if (front == NULL) {
return 0;
}
else{
if (tmp->next != NULL) {
tmp=front;
front = front->next;
delete tmp;
}
else {
tmp=front;
delete tmp;
front = NULL;
rear = NULL;
}
}
return data;
}
void Display() {
struct node* temp = front;
if (front == NULL) {
cout<<"Queue is empty"<<endl;
return;
}
while (temp != NULL) {
cout<<temp->data<<"\n";
temp = temp->next;
}
}
int Size() {
struct node* temp = front;
int cnt=0;
while (temp != NULL) {
cnt++;
temp = temp->next;
}
return cnt;
}
void Delete_at(int index){
int i=0;
int ar_size=Size();
int data_arr[ar_size-1];
if(index > Size()){
cout<<"\n"<<"Error: out of bounds !";
return;
}
while(i<ar_size){
if (i==(index-1)){
Dequeue();
}
else{
data_arr[i]=Dequeue();
}
i++;
}
i=0;
while(i<ar_size){
Enqueue(data_arr[i]);
i++;
}
}
};
int main() {
int i=0;
Queue q;
q.Enqueue(2);
q.Enqueue(6);
q.Enqueue(7);
q.Enqueue(1);
q.Enqueue(2);
q.Enqueue(4);
q.Delete_at(2);
q.Display();
return 0;
}
You have a two primary problems with your code generally, and Delete_at() cannot simply call Dequeue(). As a general note, your code contains duplicated expressions that can simply be consolidated. For example, Enqueue() can be written succinctly as:
void Enqueue(int d) {
struct node *tmp = new node;
tmp->next = nullptr;
tmp->data = d;
if (rear == nullptr) {
front = rear = tmp;
size = 1;
}
else {
rear->next = tmp;
rear = tmp;
size += 1;
}
}
Your Dequeue() function will segfault checking front->data BEFORE checking if front == nullptr. You must check before you dereference, e.g.
int Dequeue() {
struct node *tmp = front;
int data;
if (front == nullptr) { /* (must check before dereference (front->data) */
return 0;
}
data = front->data;
size -= 1;
if (tmp->next != nullptr) {
front = front->next;
}
else {
front = nullptr;
rear = nullptr;
}
delete tmp;
return data;
}
Your Delete_at() function must remove the node at a specific index. This requires that you maintain your ->next links throughout your list, updating the prev->next before the deleted node to point to the node after the one you are deleting. You do that by iterating with both the address of the node and a pointer to node. When you reach the index to remove, you simply replace what is currently at the address of that node with the next node and delete the current, see: Linus on Understanding Pointers
void Delete_at (size_t index) {
struct node *pnode = front, /* pointer to node */
**ppnode = &front; /* address of node */
if (index >= Size()) { /* validate with >= Size() */
std::cerr << '\n' << "Error: out of bounds !";
return;
}
while (index--) { /* loop index times */
ppnode = &pnode->next; /* address of next node */
pnode = pnode->next; /* pointer to next node */
}
*ppnode = pnode->next; /* replace struct at address with next */
delete pnode; /* delete removed node */
size -= 1;
}
Your Size() function simply reduces to a "getter" function:
size_t Size() {
return size;
}
Updating your example a bit and being mindful of Why is “using namespace std;” considered bad practice? your full code could now be:
#include <list>
#include <iostream>
class Queue{
private:
struct node {
int data;
struct node *next;
};
struct node *front = nullptr;
struct node *rear = nullptr;
size_t size;
public:
void Enqueue(int d) {
struct node *tmp = new node;
tmp->next = nullptr;
tmp->data = d;
if (rear == nullptr) {
front = rear = tmp;
size = 1;
}
else {
rear->next = tmp;
rear = tmp;
size += 1;
}
}
int Dequeue() {
struct node *tmp = front;
int data;
if (front == nullptr) { /* (must check before dereference (front->data) */
return 0;
}
data = front->data;
size -= 1;
if (tmp->next != nullptr) {
front = front->next;
}
else {
front = nullptr;
rear = nullptr;
}
delete tmp;
return data;
}
void Display() {
struct node *temp = front;
if (front == nullptr) {
std::cout << "Queue is empty" << '\n';
return;
}
while (temp != nullptr) {
std::cout << temp->data << '\n';
temp = temp->next;
}
}
size_t Size() {
return size;
}
void Delete_at (size_t index) {
struct node *pnode = front, /* pointer to node */
**ppnode = &front; /* address of node */
if (index >= Size()) { /* validate with >= Size() */
std::cerr << '\n' << "Error: out of bounds !";
return;
}
while (index--) { /* loop index times */
ppnode = &pnode->next; /* address of next node */
pnode = pnode->next; /* pointer to next node */
}
*ppnode = pnode->next; /* replace struct at address with next */
delete pnode; /* delete removed node */
size -= 1;
}
};
int main() {
Queue q;
q.Enqueue(2);
q.Enqueue(6);
q.Enqueue(7);
q.Enqueue(1);
q.Enqueue(2);
q.Enqueue(4);
q.Display();
std::cout << "\nq.Delete_at(2)\n\n";
q.Delete_at(2);
q.Display();
}
Example Use/Output
$ ./bin/queue_delete_at
2
6
7
1
2
4
q.Delete_at(2)
2
6
1
2
4
Look things over and let me know if you have further questions.
Edit With Additional Constraints From Comments
Per you comments, you have constraints of only being able to use Dequeue() and Enqueue() in Delete_at() and no pointers, etc... You can do that, but understand it will be horribly inefficient compared to simply removing the node at the index. You will essentially have to save (Dequeue()) your entire queue data in an allocated block of memory, omitting the index to remove. You will then need to iterate over all saved values calling Enqueue() to repopulated your list.
You can do that as:
void Delete_at (size_t index) {
if (index >= Size()) { /* validate with >= Size() */
std::cerr << '\n' << "Error: out of bounds !";
return;
}
size_t nelem = Size();
int *arr = new int [nelem],
n = 0;
for (size_t i = 0; i < nelem; i++) {
int tmp = Dequeue();
if (i != index && tmp)
arr[n++] = tmp;
}
for (size_t i = 0; i < (size_t)n; i++)
Enqueue (arr[i]);
delete[] arr;
}
(same output)
For a less readable more C++'ized presentation, you can replace the first loop with:
for (int i = 0, j = Dequeue(); j; i++, j = Dequeue())
if (static_cast<size_t>(i) != index)
arr[n++] = j;
It would be nice to have utilized at least a separate list pointer, so you could build the new list while simultaneously deleting the old, but your class/struct isn't setup to use additional pointers. So you are basically left with buffering all values except the index to remove and then recreating your queue.
Related
I have implemented a method to insert a new node before a specific node.
#ifndef FORWARD_SINGLY_LINKED_LIST_H
#define FORWARD_SINGLY_LINKED_LIST_H
#include <cstdlib>
#include <string.h>
#include <iostream>
namespace forward_singly_linked_list {
typedef struct Node {
std::string data;
struct Node *nextPointer;
} Node;
typedef Node *NodeP;
class LinkedList {
private:
int elementsCount;
Node *head;
public:
LinkedList() {
head = NULL;
elementsCount = 0;
}
int get_length() const
{
return elementsCount;
}
// ... ... ...
void add_before(std::string value, std::string before)
{
// empty an area in the memory, and
// save the address of the empty area in 'newNode'
Node *newNode = new Node();
// assign 'value' to the 'data' section of the
// area pointed by 'newNode'
newNode->data = value;
Node * copyOfHead = head;
if (copyOfHead == nullptr)
{
// the list is empty.
// there is no possibility to find 'before'.
// so, return.
return;
}
else
{
bool found = false;
Node * previousNode = nullptr;
while (copyOfHead != nullptr)
{
if (copyOfHead->data == before)
{
found = true;
break;
}
else
{
previousNode = copyOfHead;
copyOfHead = copyOfHead->nextPointer;
}
}
if (!found)
{
return;
}
if (previousNode != nullptr)
{
newNode->nextPointer = previousNode->nextPointer;
previousNode->nextPointer = newNode;
}
else
{
newNode->nextPointer = head;
head = newNode;
}
}
elementsCount++;
}
// ... ... ...
void print() {
Node *copyOfHead = head;
while (copyOfHead != NULL) {
std::cout << copyOfHead->data;
copyOfHead = copyOfHead->nextPointer;
}
std::cout<<"\n\n";
}
public:
static int Test() {
forward_singly_linked_list::LinkedList list;
list.print();
// list.add_at_tail("A");
// list.add_at_tail("B");
// list.add_at_tail("C");
list.print();
list.add_at("-XXX-", 1);
list.print();
return 0;
}
};
}
#endif
Personally, I don't like it because it uses an extra pointer previousNode. I have a feeling that it could be improved.
How can I improve the implementation?
The idea is about link the previous node to input/target node, then link the target/input node to current node.
Here is my code using simple loop index(i) instead of using extra pointer
void Sll::add_at_index( int ind , int value ){
Node *target = new Node( value ) ;
if( ind == 1){
target->next = head ;
head = target ;
}else if( ind == length){
tail->next = target ;
tail = target ;
tail->next = nullptr ;
}else{
Node *curr =head ;
for( int i = 1 ; i < length ; i++ ){
if( i+1 == ind){
Node *Mynext = curr->next ;
curr->next = target ;
target->next = Mynext ;
break ;
}
curr = curr->next ;
}
}
length++ ;
}
Become a two-star programmer:
void add_before(std::string value, std::string_view before) {
auto p = &head;
while (*p && (*p)->data != before)
p = &(*p)->nextPointer;
if (!*p)
return;
*p = new Node {
.data = std::move(value),
.nextPointer = *p,
};
++elementsCount;
}
I am trying to implement merge sort in a linked list in c++. When I execute my code, it runs infinitely no. of time. When I debug it, I found that my mergesort function runs only for the left half infinite number no. of times.I mean it never comes out from left half. That function never called for the right half. I am pasting my whole code link here. Can anyone tell me why the function runs infinitely and what modifications I have to make to my code?
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007
struct Node {
int data;
struct Node* link;
};
Node* head = NULL;
void ins(int data, int pos)
{
Node* ptr = new Node();
ptr->data = data;
ptr->link = NULL;
if (pos == 1) {
ptr->link = head;
head = ptr;
return;
}
Node* temp = new Node();
temp = head;
for (int i = 1; i < pos - 1; i++) {
temp = temp->link;
}
ptr->link = temp->link;
temp->link = ptr;
return;
}
Node* getmid(Node* temp)
{
if (temp == 0) {
return temp;
}
Node* a = temp;
Node* b = temp;
while (b->link != 0) {
b = b->link;
a = a->link;
if (b->link != 0) {
b = b->link;
}
else {
break;
}
}
return a;
}
Node* merge(Node* left, Node* right)
{
Node* res = NULL;
if (left == NULL || right == NULL) {
if (left == NULL) {
return right;
}
if (right == NULL) {
return left;
}
else {
return NULL;
}
}
else if ((left->data) < (right->data)) {
res = left;
res->link = merge(left->link, right);
}
else {
res = right;
res->link = merge(left, right->link);
}
return res;
}
Node* mergesort(Node* head)
{
if (head == NULL || (head->link) == NULL) {
return head;
}
Node* mid = getmid(head);
Node* left = head;
Node* right = mid->link;
mid->link = NULL;
left = mergesort(left);
right = mergesort(right);
Node* c = merge(left, right);
return c;
}
void display()
{
Node* t = head;
while (t != 0) {
cout << t->data << " ";
t = t->link;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
ins(8, 1);
ins(23, 2);
ins(73, 3);
ins(4, 4);
ins(5, 5);
ins(7, 6);
mergesort(head);
display();
}
In the above code, ins function is used to insert the node. getmid function is used for getting the address of the middle node. merge function is used to sort the left and right half. And mergesort function is used to divide the list into 2 half and call each half.display function is used for print linked list
Maybe this can help you.
#include <bits/stdc++.h>
using namespace std;
/* Link list node */
class Node {
public:
int data;
Node* next;
};
/* function prototypes */
Node* SortedMerge(Node* a, Node* b);
void FrontBackSplit(Node* source,
Node** frontRef, Node** backRef);
/* sorts the linked list by changing next pointers (not data) */
void MergeSort(Node** headRef)
{
Node* head = *headRef;
Node* a;
Node* b;
/* Base case -- length 0 or 1 */
if ((head == NULL) || (head->next == NULL)) {
return;
}
/* Split head into 'a' and 'b' sublists */
FrontBackSplit(head, &a, &b);
/* Recursively sort the sublists */
MergeSort(&a);
MergeSort(&b);
/* answer = merge the two sorted lists together */
*headRef = SortedMerge(a, b);
}
/* See https:// www.geeksforgeeks.org/?p=3622 for details of this
function */
Node* SortedMerge(Node* a, Node* b)
{
Node* result = NULL;
/* Base cases */
if (a == NULL)
return (b);
else if (b == NULL)
return (a);
/* Pick either a or b, and recur */
if (a->data <= b->data) {
result = a;
result->next = SortedMerge(a->next, b);
}
else {
result = b;
result->next = SortedMerge(a, b->next);
}
return (result);
}
/* UTILITY FUNCTIONS */
/* Split the nodes of the given list into front and back halves,
and return the two lists using the reference parameters.
If the length is odd, the extra node should go in the front list.
Uses the fast/slow pointer strategy. */
void FrontBackSplit(Node* source,
Node** frontRef, Node** backRef)
{
Node* fast;
Node* slow;
slow = source;
fast = source->next;
/* Advance 'fast' two nodes, and advance 'slow' one node */
while (fast != NULL) {
fast = fast->next;
if (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
}
/* 'slow' is before the midpoint in the list, so split it in two
at that point. */
*frontRef = source;
*backRef = slow->next;
slow->next = NULL;
}
/* Function to print nodes in a given linked list */
void printList(Node* node)
{
while (node != NULL) {
cout << node->data << " ";
node = node->next;
}
}
/* Function to insert a node at the beginging of the linked list */
void push(Node** head_ref, int new_data)
{
/* allocate node */
Node* new_node = new 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;
}
/* Driver program to test above functions*/
int main()
{
/* Start with the empty list */
Node* res = NULL;
Node* a = NULL;
/* Let us create a unsorted linked lists to test the functions
Created lists shall be a: 2->3->20->5->10->15 */
push(&a, 15);
push(&a, 10);
push(&a, 5);
push(&a, 20);
push(&a, 3);
push(&a, 2);
/* Sort the above created Linked List */
MergeSort(&a);
cout << "Sorted Linked List is: \n";
printList(a);
return 0;
}
The issue was in getmid()
For lists of 2 elements it returned the second element, instead of the first.
Therefore with 2 elements left always pointed to the whole list, causing an infinite recursion.
Node* getmid(Node* temp)
{
if (temp == nullptr)
return nullptr;
if (temp->link == nullptr)
return temp;
Node* a = temp;
//---------------------------------
Node* b = temp->link; // Here!
//---------------------------------
while (b->link != nullptr) {
b = b->link;
a = a->link;
if (b->link != nullptr)
b = b->link;
else
break;
}
return a;
}
You can run it here: https://onlinegdb.com/3fhqQyBhy
I'm using nullptr instead of NULL or 0 and I'm passing the list as a parameter to the insert function
I am trying to implement a priority Queue by using a linked list in c++. However, when I run the program it triggers a breakpoint within "priorityQLinkedList::dequeue()" method. Can someone tell why this is the case and give me suggestions on how to fix it?
Code:
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
struct DAT
{
int id;
char fullname[50];
double savings;
};
struct NODE
{
DAT data;
NODE *N;
NODE *P;
NODE(const int i, const char *f, const double s)
{
data.id = i;
strcpy_s(data.fullname, f);
data.savings = s;
N = NULL;
P = NULL;
}
};
class priorityQLinkedList
{
private:
NODE *front;
NODE *back;
public:
priorityQLinkedList() { front = NULL; back = NULL; }
~priorityQLinkedList() { destroyList(); }
void enqueue(NODE *);
NODE* dequeue();
void destroyList();
};
void priorityQLinkedList::enqueue(NODE *n)
{
if (front == NULL) {
front = n;
back = n;
}
else {
NODE *temp = front;
if (n->data.id > temp->data.id)
{
front->P = n;
n->N = front;
front = n;
}
else
{
//search for the posistion for the new node.
while (n->data.id < temp->data.id)
{
if (temp->N == NULL) {
break;
}
temp = temp->N;
}
//New node id's smallest then all others
if (temp->N == NULL && n->data.id < temp->data.id)
{
back->N = n;
n->P = back;
back = n;
}
//New node id's is in the medium range.
else {
temp->P->N = n;
n->P = temp->P;
n->N = temp;
temp->P = n;
}
}
}
}
NODE* priorityQLinkedList::dequeue()
{
NODE *temp;
//no nodes
if (back == NULL) {
return NULL;
}
//there is only one node
else if (back->P == NULL) {
NODE *temp2 = back;
temp = temp2;
front = NULL;
back = NULL;
delete temp2;
return temp;
}
//there are more than one node
else {
NODE *temp2 = back;
temp = temp2;
back = back->P;
back->N = NULL;
delete temp2;
return temp;
}
}
void priorityQLinkedList::destroyList()
{
while (front != NULL) {
NODE *temp = front;
front = front->N;
delete temp;
}
}
void disp(NODE *m) {
if (m == NULL) {
cout << "\nQueue is Empty!!!" << endl;
}
else {
cout << "\nID No. : " << m->data.id;
cout << "\nFull Name : " << m->data.fullname;
cout << "\nSalary : " << setprecision(15) << m->data.savings << endl;
}
}
int main() {
priorityQLinkedList *Queue = new priorityQLinkedList();
NODE No1(101, "Qasim Imtiaz", 567000.0000);
NODE No2(102, "Hamad Ahmed", 360200.0000);
NODE No3(103, "Fahad Ahmed", 726000.0000);
NODE No4(104, "Usmaan Arif", 689000.0000);
Queue->enqueue(&No4);
Queue->enqueue(&No3);
Queue->enqueue(&No1);
Queue->enqueue(&No2);
disp(Queue->dequeue());
disp(Queue->dequeue());
disp(Queue->dequeue());
disp(Queue->dequeue());
disp(Queue->dequeue());
delete Queue;
return 0;
}
One problem which stands out in your dequeue() method is that you are calling delete on a NODE pointer, and then attempting to return this deleted pointer to the caller. This could cause an error either in dequeue() itself, or certainly in the caller who thinks he is getting back a pointer to an actual live NODE object.
One potential fix would be to create a copy of the NODE being dequeued. You would still remove the target from your list, but the caller would then be returned a valid pointer, which he could free later.
NODE* priorityQLinkedList::dequeue()
{
NODE *temp;
// no nodes
if (back == NULL) {
return NULL;
}
NODE *temp2 = back;
temp = new NODE(temp2->data.id, temp2->data.fullname, temp2->data.savings);
// there is only one node
else if (back->P == NULL) {
front = NULL;
back = NULL;
delete temp2;
return temp;
}
// there are more than one node
else {
back = back->P;
back->N = NULL;
delete temp2;
return temp;
}
}
You're deleting pointers in dequeue that priorityQLinkedList does not own, so you don't know if it is safe to delete them.
In this case, they are not since the node pointers passed to enqueue are addresses of local, stacked based variables and have not been allocated by new. (There's also the already mentioned problem of deleting a pointer then returning it, which is Undefined Behavior.)
The fix for the code as shown is to remove the calls to delete in dequeue. However, if changes are made so that the nodes passed to enqueue are dynamically allocated, you'll need to add something to handle that.
1.First change strcpy_s to strcpy is struct NODE.
2.Instead of Delete(temp2) use temp2--.
//no nodes
if (back == NULL) {
return NULL;
}
//there is only one node
else if (back->P == NULL) {
NODE *temp2 = back;
temp = temp2;
front = NULL;
back = NULL;
temp2--;
return temp;
}
//there are more than one node
else {
NODE *temp2 = back;
temp = temp2;
back = back->P;
back->N = NULL;
temp2--;
return temp;
}
I hope this will resolve the problem.
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
Why does the above error occur when calling showNode()?
#include<iostream>
#define NULL 0
using namespace std;
class myNode{
private:
int data;
myNode* link;
myNode* first;
public:
myNode(){
data=0;
link=NULL;
first=NULL;
}
void insertNode(int value, int iposition){
myNode n;
if (iposition==1)
{
first=&n;
cout<<first<<endl;
n.data=value;
n.link=NULL;
}
if (iposition>1)
{
int nodeCounter=1;
myNode* temp=first;
while (temp->link != NULL)
{
nodeCounter++;
}// this while counts the number of inserted nodes.
if (iposition>nodeCounter)//if the position of the new node is greater than number of inserted node,
//it will be inserted at the end.
{
cout<<"Node will be inserted at end."<<endl;
myNode* ieTemp=first;
while (ieTemp->link != NULL)
{
ieTemp=ieTemp->link;
cout<<ieTemp->data<<endl;
}
ieTemp->link=&n;
n.data=value;
n.link=NULL;
cout<<&n<<" ";
}
else
{
myNode* imTemp=first;
while (iposition-1)
{
imTemp=imTemp->link;
iposition--;
}
n.link=imTemp->link;
n.data=value;
imTemp->link=&n;
}
}
}//end insertNode
void showNode(){
myNode* sTemp=first;
while (sTemp != NULL)
{
cout<<sTemp->data<<" ";
sTemp=sTemp->link;
}
}//end showNode
};
int main(){
myNode a;
a.insertNode(10,1);
a.insertNode(20,2);
a.insertNode(25,3);
a.insertNode(30,4);
a.insertNode(40,5);
a.showNode();
system("pause");
}
First you must declare myNode *n = new myNode(); because you use it outside of insertNode function. Second you may want to check if first node exist to avoid error on inserting first node on any other position than 1 (in your case if your first insert will be like inserNode(x, y != 1) will throw an error because you try to access first node (here: while (temp->link != NULL))) but this node don't exist.
This is what I think you want:
void insertNode(int value, int iposition){
myNode *n = new myNode();
myNode *cur = first;
//insert first node or on first position
if (cur == NULL || iposition <= 1) {
n->data = value;
if (cur == NULL) { //first node
n->link = NULL;
}
else { //first position
n->link = first;
}
first = n;
return;
}
for (int i = 1; i < iposition - 1; i++) { //find given position
if (cur->link == NULL) { //if end
n->data = value;
n->link = NULL;
cur->link = n;
return;
}
cur = cur->link;
}
//here we are on position = iposition-1
n->data = value;
n->link = cur->link;
cur->link = n;
}//end insertNode