C++ - How to subtract two Linked Lists from one another? - c++

I am trying to make a way to take two Linked List objects (doubly-linked), say LL1 and LL2, and remove the 'overlapping' elements within LL1 which also appear in LL2.
So for example if:
LL1 = {1,2,3};
LL2 = {9,2,8};
I want an output of:
LL1 = {1,3};
I am trying to do this via overloading the '-=' operator to work with two linked list objects. It compiles fine, but I'm getting a 'segmentation fault (core dumped)' error during runtime at the '-=' operator call. Not sure why. Below is my code. Any help would be appreciated, thankyou kindly.
Node.h:
// Node.h
/*******************************/
// Last Updated: Tues Aug 31 2021
// Program Description: Header file for Node
#ifndef NODE_H
#define NODE_H
#include <iostream>
#include <cstdlib>
#include "EToll.h"
using namespace std;
class Node {
public:
typedef EToll value_type; //typedef - now value_type is synonym for EToll object
//Constructors:
Node(); //default
Node(value_type&); //constructor with 1 arg - data item
Node(const value_type& i, Node* n, Node* p); //specific constructor with 3 arguments
//Destructor:
~Node();
//mutators (setters):
void set_next(Node*);
void set_prev(Node*);
void set_data(const value_type&);
//accessors (getters):
Node* get_next() const;
Node* get_prev() const;
value_type& get_data();
private:
Node* next; //ptr to next (or NULL)
Node* prev; //ptr to prev (or NULL)
value_type data; //the payload
};
#endif
Node.cpp:
// Node.cpp
/*******************************/
// Last Updated: Tues Aug 31 2021
// Program Description: Implementation of Node
#include "Node.h"
#include <cstdlib>
//Constructors:
Node::Node() //default constructor
{
data = value_type(); //creates an empty EToll object, since value_type is a synonym for EToll
next = NULL;
prev = NULL;
}
Node::Node(value_type& item) //constructor with 1 argument - a data item
{
data = item;
next = NULL;
prev = NULL;
}
Node::Node(const value_type& i, Node* n, Node* p) //constructor with 3 arguments
{
data = i;
next = n;
prev = p;
}
//Empty destructor:
Node::~Node(){}
//Mutators (setters):
void Node::set_next(Node* next_ptr) {next = next_ptr;}
void Node::set_prev(Node* prev_ptr) {prev = prev_ptr;}
void Node::set_data(const value_type& new_data) {data = new_data;}
//Accessors (getters):
Node* Node::get_next() const {return next;}
Node* Node::get_prev() const {return prev;}
/* Note that get_data() has Node::value_type& instead of value_type& as it's return type as the
compiler doesn't check if the return type of a function is part of a member function, and thus
it doesn't look in Node for a value_type. A more detailed explanation can be found at: https://stackoverflow.com/questions/68991650/error-value-type-does-not-name-a-type-in-c */
Node::value_type& Node::get_data() {return data;}
LinkedList.h:
// LinkedList.h
/*******************************/
// Last Updated: Tues Aug 31 2021
// Program Description: Header file for LinkedList
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "Node.h"
#include <iostream>
#include <cstdlib>
#include <string>
class LinkedList
{
public:
typedef Node::value_type value_type;
//Constructor:
LinkedList();
//Destructor:
~LinkedList();
//Insert function:
//void insert(value_type& item);
//length function:
int length();
//count function:
int count(string);
//totalIncome function:
double totalIncome();
//addTo functions:
void addToHead(value_type&);
void addToTail(value_type&);
//accessors (getters):
value_type& getHead();
Node* getHeadAdd();
value_type& getTail();
//remove functions:
void removeFromHead();
void removeFromTail();
void remove(string);
void removeByNode(Node* c); //remove a particular node
//search funciton:
//Preconditions: None
//Postconditions: Current points to the first Node storing the target, and true is returned. If not present, current is NULL and false is returned
bool search(const value_type& target);
//concatenation operator (+=) overload:
//Preconditions: LL1 and LL2 are instances of LinkedList
//Postconditions: Each Node of LL2 is traversed. At each individual Node, itis appended to LL1
LinkedList operator += (const LinkedList& LL2);
//remove overlap operator (-=) overload:
//Preconditions: LL1 and LL2 are instances of LinkedList
//Postconditions: Each Node of LL2 is traversed. At each individual Node, it's match is searched for within LL1. If a match is found, the matching Node in LL1 is deleted and the next node in LL2 is traversed
LinkedList operator -= (const LinkedList& LL2);
//NEED A .COUNT FUNCTION!!
private:
Node* head;
Node* tail;
Node* current;
};
//stream insertion operator (<<) overload:
//Preconditions: LinkedList obj "LL" exists and we wish to output it
//Postconditions: LL exists without change
ostream& operator << (ostream& out, LinkedList& LL);
#endif
LinkedList.cpp:
// LinkedList.cpp
/*******************************/
// Last Updated: Wed Aug 31 2021
// Program Description: Implementation of LinkedList
#include "LinkedList.h"
#include <cstdlib>
//Constructors:
LinkedList::LinkedList() //default constructor
{
head = NULL;
tail = NULL;
current = NULL;
}
//Empty destructor:
LinkedList::~LinkedList(){}
//length() function:
//Preconditions: None
//Postconditions: A count of the nodes is returned (ie no of nodes in the LinkedList)
int LinkedList::length()
{
int answer = 0;
for (current = head; current != NULL; current = current->get_next())
{
answer++;
}
return answer;
}
//count function:
int LinkedList::count(string type)
{
int returnCount = 0;
//cycle through LinkedList:
for (current = head; current != NULL; current = current->get_next())
{
//check for match:
if (type == current->get_data().get_type())
{
//increment the counter
returnCount++;
}
}
return returnCount;
}
//totalIncome function:
double LinkedList::totalIncome()
{
double returnTotal = 0;
//cycle through LinkedList:
for (current = head; current != NULL; current = current->get_next())
{
returnTotal = returnTotal + current->get_data().get_charge();
}
return returnTotal;
}
//addToHead function:
//Preconditions: None
//Postconditions: A new node storing the supplied item is created and linked in to be list's new head
void LinkedList::addToHead(Node::value_type& item)
{
Node* newNode = new Node(item);
//Check if the list is empty:
if (length() == 0)
{ //list is empty, so:
head = newNode;
tail = newNode;
} else
{ //list is not empty, so:
head->set_prev(newNode);
newNode->set_next(head);
head = newNode;
}
/*
head = new Node(item, head, NULL);
//In case the list is empty:
if (tail == NULL)
{
tail = head;
}
*/
}
//addToTail function:
//Preconditions: None
//Postconditions: A new node storing the supplied item is created and linked in to be list's new tail
void LinkedList::addToTail(Node::value_type& item)
{
Node* newNode = new Node(item);
//Check if the list is empty:
if (length() == 0)
{ //list is empty, so:
head = newNode;
tail = newNode;
} else
{ //list is not empty, so:
tail->set_next(newNode);
newNode->set_prev(tail);
tail = newNode;
}
}
//getHead function:
Node::value_type& LinkedList::getHead()
{
return head->get_data();
}
//getHeadAdd function:
Node* LinkedList::getHeadAdd()
{
return head->get_next()->get_prev();
}
//getTail function:
Node::value_type& LinkedList::getTail()
{
return tail->get_data();
}
//removeFromHead function:
void LinkedList::removeFromHead()
{
Node* temp;
temp = head->get_next();
if (head != NULL)
{
temp->set_prev(NULL);
head = temp;
} else
{ //list is empty, so update the tail
tail = NULL;
}
}
//removeFromTail function:
void LinkedList::removeFromTail()
{
Node* temp;
temp = tail->get_prev();
if (head != NULL)
{
temp->set_next(NULL);
tail = temp;
} else
{ //list is empty, so update the head
head = NULL;
}
}
//remove function: removes a Node by a string input
void LinkedList::remove(string l)
{
//cycle through LinkedList:
for (current = head; current != NULL; current = current->get_next())
{
//check for match:
if (l == current->get_data().get_licence() && current == head)
{
removeFromHead();
} else if (l == current->get_data().get_licence() && current == tail)
{
removeFromTail();
} else if (l == current->get_data().get_licence())
{
//delete the node
removeByNode(current);
} else
{
//do nothing, move on to next iteration of for loop
}
}
}
//removeByNode function:
//Preconditions: input c points to a node to be removed
//Postconditions: the node pointed to by c before is now gone. current now points to head
void LinkedList::removeByNode(Node* c)
{
current = c;
current->get_prev()->set_next(current->get_next());
current->get_next()->set_prev(current->get_prev());
delete current;
current = head;
}
//search function:
bool LinkedList::search(const Node::value_type& target)
{
for (current = head; current != NULL; current = current->get_next())
{
if (target == current->get_data())
{
return true;
}
}
//else:
return false;
}
// += operator overload (new):
LinkedList LinkedList::operator += (const LinkedList& LL2)
{
LinkedList* t = this;
Node* temp = LL2.head;
while (temp != NULL)
{
t->addToTail(temp->get_data());
temp = temp->get_next();
}
return *t;
}
// -= operator overload:
LinkedList LinkedList::operator -= (const LinkedList& LL2)
{
LinkedList* t = this;
Node* temp1;
Node* temp2;
//Cycle through LL2:
for (temp2 = LL2.head; temp2 != NULL; temp2 = temp2->get_next())
{
//Cycle through LL1:
for (temp1 = t->head; temp1 != NULL; temp1 = temp1->get_next())
{
//Check if current of LL1 has a match in LL2:
if (temp1->get_data() == temp2->get_data())
{
t->removeByNode(temp1);
}
}
}
return *t;
}
-= operator overload (within LinkedList.cpp, just putting it here under new heading for easy location):
// -= operator overload:
LinkedList LinkedList::operator -= (const LinkedList& LL2)
{
LinkedList* t = this;
Node* temp1;
Node* temp2;
//Cycle through LL2:
for (temp2 = LL2.head; temp2 != NULL; temp2 = temp2->get_next())
{
//Cycle through LL1:
for (temp1 = t->head; temp1 != NULL; temp1 = temp1->get_next())
{
//Check if current of LL1 has a match in LL2:
if (temp1->get_data() == temp2->get_data())
{
t->removeByNode(temp1);
}
}
}
return *t;
}
-= operator call within another 'main()' program:
LinkedList tollBooth1;
LinkedList tollBooth2;
LinkedList dailyReport;
//(add data to tollBooth 1 and 2, merge these 2 objects into dailyReport)
//removing the contents of both booths from daily report:
dailyReport -= tollBooth1;
dailyReport -= tollBooth2;

You've included way too much code. The general ask on this site is to provide a minimal reproducible example.
Problems
I have no idea why you have a member variable named current. It often points to deleted memory.
You need to implement the "rule of three" or the "rule of five" on your LinkedList class. If you copy the LinkedList, and then modify it, you will have dangling pointers.
LinkedList a;
LinkedList b = a;
a.RemoveHead();
// b.head is now pointing to deleted memory.
LinkedList::removeByNode(Node* c) does not update the head and tail member variables if the removed node was the head or tail respectively.
Your operator-= uses temp1 after it has been deleted.
There are likely more issues.

Related

Add integer to each item of unordered linked list

I want to write a function that adds an integer (passed as an argument to the function) to each item in the unordered linked list. Here is the complete program.
#include <iostream>
using namespace std;
//creates a node class
class Node {
//defines data, and next as a pointer.
private:
int data; //data in the beginning node
Node *next; //pointer to the next node
public:
Node(int initdata) {
data = initdata; //the initialized data is set as the head
next = NULL; //the next node is set as NULL, as there is no next node yet.
}
int getData() { //function that return data of a given node.
return data;
}
Node *getNext() { // pointer that gets the next node
return next;
}
void setData(int newData) { // sets data in node
data = newData;
}
void setNext(Node *newnext) {
next = newnext;
}
};
// creates unorderedlist that points to the head of the linked list
class UnorderedList {
public:
Node *head;
UnorderedList() { // makes the head node equal to null
head = NULL;
}
bool isEmpty() { // the head node is empty if it is null
return head == NULL;
}
void add(int item) { //cerates a "temp" pointer that adds the new node to the head of the list
Node *temp = new Node(item);
temp->setNext(head);
head = temp;
}
int size() { //cereates a "current" pointer that iterates through the list until it reaches null
Node *current = head;
int count = 0;
while (current != NULL) {
count++;
current = current->getNext();
}
return count;
}
// creates "current" pointer that iterates through the list
// untli it finds the item being searched for, and returns a boolean value
bool search(int item) {
Node *current = head;
while (current != NULL) {
if (current->getData() == item) {
return true;
} else {
current = current->getNext();
}
}
return false;
}
void addInteger(int item){
Node *current = head;
while (current != NULL) {
current->getData() = current->getData() + item;
}
}
// uses current and previous pointer to iterate through the lists
// finds the items that is searched for, and removes it
void remove(int item) {
Node *current = head;
Node *previous = NULL;
bool found = false;
while (!found) {
if (current->getData() == item) {
found = true;
} else {
previous = current;
current = current->getNext();
}
}
if (previous == NULL) {
head = current->getNext();
} else {
previous->setNext(current->getNext());
}
}
friend ostream& operator<<(ostream& os, const UnorderedList& ol);
};
ostream& operator<<(ostream& os, const UnorderedList& ol) {
Node *current = ol.head;
while (current != NULL) {
os<<current->getData()<<endl;
current = current->getNext();
}
return os;
}
int main() {
UnorderedList mylist;
mylist.add(1);
mylist.add(2);
mylist.add(3);
mylist.add(4);
mylist.add(5);
mylist.add(6);
cout<<"MY LIST: "<<endl<<mylist;
mylist.addInteger(5);
cout<<"=========================================================\n";
cout<<"After adding 5 to each element, the list now is\n";
cout<<"MY LIST: "<<endl<<mylist;
return 0;
}
Now the program shows an error in the following function from the program above regarding the assignment operation.
void addInteger(int item){
Node *current = head;
while (current != NULL) {
current->getData() = current->getData() + item;
}
}
How can I add a number to each element of the linked list?
Any help is appreciated.
You probably want something like the following:
current->setData(current->getData() + item);
Note that now you are retrieving a return value in the left-hand side, then trying to assign to it. This is what your compiler is telling you, presumably.

C++ program running smoothly on VS but not on Linux Mint

For some reason when i run my C++ program on VS it compile and run smoothly and when i'm trying to run it on Linux Mint terminal it does compile without any errors but i'm not getting any feedback/printing to the terminal...it's just stuck - so i can't even guess where the problem is. any suggestions?
I'm really a noob when it comes to Linux...
my program contains 2 cpp class file, 2 header files (each for one class) and a main.cpp file which i'm trying to run like this:
g++ *.cpp -o myprog
./myprog
it does create a myprog file - but when i run it nothing happens, like i said.
my code:
btree.h
#include <iostream>
#ifndef _BTREE_H_
#define _BTREE_H_
class LinkedList;
struct node
{
int key_value;
node *left;
node *right;
};
class btree
{
friend class LinkedList;
public:
// Default constructor
btree();
~btree();
// Copy Constructor by list
btree(LinkedList &list);
// Copy Constructor by tree
btree(btree & bt);
// assignment operator from linked list
btree & operator=(const LinkedList & ls);
// assignment operator from tree
btree& operator=(const btree &bt);
// insert new value to binary tree
void insert(int key);
// mirror the tree
void mirror();
LinkedList* Tree2linkListbyDepth();
int getTreeDepth();
// print tree (in order)
friend std::ostream& operator<<(std::ostream& os, btree& dt);
private:
node* root;
bool isMirrored;
void copyConstructor(node *bt);
void destroyTree(node * tmp);
void insert(node* tmp, int key);
void mirrorInsert(node* tmp, int key);
void mirror(node * node);
LinkedList TreeToList(node *tmp, LinkedList *listToReturn, int depth);
int getTreeDepth(node * tmp);
friend std::ostream& travel(std::ostream & os, node* root);
};
#endif // _BTREE_H_
btree.cpp
#include"btree.h"
#include"Linkedlist.h"
#include<iostream>
using namespace std;
//constructor
btree::btree()
{
root = NULL;
isMirrored = false;
}
//destructor
btree::~btree()
{
destroyTree(this->root);
}
void btree::destroyTree(node * tmp)
{
if (tmp == NULL)
return;
destroyTree(tmp->left);
destroyTree(tmp->right);
delete(tmp);
}
//copy constructor - list to binary tree.
btree::btree(LinkedList &list)
{
while (list.head!=NULL)
{
insert(list.head->data);
list.head = list.head->next;
}
}
//copy constructor - inorder.
btree::btree(btree & bt)
{
if (bt.root == NULL)
root = NULL;
else
copyConstructor(bt.root);
}
void btree::copyConstructor(node *bt)
{
node* tmp = bt;
if (!tmp)
return;
copyConstructor(tmp->left);
insert(tmp->key_value);
copyConstructor(tmp->right);
}
//copying list to binary tree using "=" operator.
btree & btree::operator=(const LinkedList & ls)
{
Node *tmp = ls.head;
while (tmp != NULL)
{
insert(tmp->data);
tmp = tmp->next;
}
return *this;
}
//copying binary trees using "=" operator
btree & btree::operator=(const btree & bt)
{
if (this->root == bt.root) //cheking if not itself
return *this;
//למחוק את העץ הקיים
copyConstructor(bt.root);
return *this;
}
//inserting node to the binary tree
void btree::insert(int key)
{
node *tmp = root;
if (root != NULL)
{
if (isMirrored) //checking if the tree has been mirrored
mirrorInsert(tmp, key);
else
insert(tmp, key);
}
//if the tree is empty - adding a new node
else
{
root = new node;
root->key_value = key;
root->left = NULL;
root->right = NULL;
}
}
//regular insertion - smaller numbers to the left and bigger numbers to the right of the root.
void btree::insert(node* tmp, int key)
{
if (tmp->key_value >= key)
{
if (tmp->left == NULL)
{
tmp->left = new node();
tmp->left->key_value = key;
tmp->left->left = NULL;
tmp->left->right = NULL;
return;
}
insert(tmp->left, key);
}
else if (tmp->key_value < key)
{
if (tmp->right == NULL)
{
tmp->right = new node();
tmp->right->key_value = key;
tmp->right->left = NULL;
tmp->right->right = NULL;
return;
}
insert(tmp->right, key);
}
}
//mirrored insertion - smaller numbers to the right and bigger numbers to the left of the root.
void btree::mirrorInsert(node* tmp, int key)
{
if (tmp->key_value <= key)
{
if (tmp->left == NULL)
{
tmp->left = new node();
tmp->left->key_value = key;
tmp->left->left = NULL;
tmp->left->right = NULL;
return;
}
mirrorInsert(tmp->left, key);
}
else if (tmp->key_value > key)
{
if (tmp->right == NULL)
{
tmp->right = new node();
tmp->right->key_value = key;
tmp->right->left = NULL;
tmp->right->right = NULL;
return;
}
mirrorInsert(tmp->right, key);
}
}
//mirroring the binary tree and keeping track of it.
void btree::mirror()
{
if (isMirrored)
isMirrored = false;
else
isMirrored = true;
mirror(root);
}
void btree::mirror(node * node)
{
if (node == NULL)
return;
else
{
struct node * tmp;
mirror(node->left);
mirror(node->right);
tmp = node->left;
node->left = node->right;
node->right = tmp;
}
}
//constructing a list of lists, each list contains all the nodes at a specific level(depth).
LinkedList* btree::Tree2linkListbyDepth()
{
if (this == NULL)
return NULL;
node *tmp = root;
LinkedList *list;
int depth = this->getTreeDepth();
list = new LinkedList[depth]; //list of lists
for (int i = 0; i < depth; i++)
{
TreeToList(tmp, &list[i],(depth-i)); //adding to list[i] all the node in (depth-i) level from the binary tree using "TreeToList"
}
return list;
}
//returning a list with all the node at a specific level (depth).
LinkedList btree::TreeToList(node *tmp, LinkedList *listToReturn, int depth)
{
if (tmp == NULL)
return *listToReturn;
else if (getTreeDepth(tmp) == depth)
listToReturn->add(tmp->key_value);
else
{
TreeToList(tmp->left, listToReturn, depth);
TreeToList(tmp->right, listToReturn, depth);
}
return *listToReturn;
}
//returning the binary tree's depth.
int btree::getTreeDepth()
{
if (this->root == NULL)
return 0;
node* tmp = root;
return getTreeDepth(tmp);
}
int btree::getTreeDepth(node * tmp)
{
if (tmp == NULL)
return 0;
int leftDepth = getTreeDepth(tmp->left);
int rightDepth = getTreeDepth(tmp->right);
if (leftDepth > rightDepth)
return leftDepth+1;
else
return rightDepth+1;
}
ostream & travel(ostream &os, node* root)
{
node* tmp = root;
if (!root)
return os;
travel(os, root->left);
os << root->key_value << ",";
travel(os, root->right);
return os;
}
//printing the binary tree inorder - using recursive function "travel".
ostream & operator<<(ostream & os, btree & dt)
{
os << "Tree: ";
travel(os, dt.root);
os << endl;
return os;
}
Linkedlist.h
#include <iostream>
#ifndef _LINKEDLIST_H_
#define _LINKEDLIST_H_
class btree;
class Node
{
public:
Node* next;
int data;
};
using namespace std;
class LinkedList
{
friend class btree;
public:
int length;
Node* head;
LinkedList(btree &bt);
LinkedList(LinkedList &bt);
LinkedList();
~LinkedList();
void add(int data);
LinkedList & operator=(const LinkedList & bt);
LinkedList& operator=(const btree &bt);
friend std::ostream& operator<<(std::ostream& os, LinkedList& l);
private:
void copyBtToList(struct node *bt);
LinkedList(const LinkedList &bt);
void addToTail(int data);
};
#endif // !_LINKEDLIST_H_
Linkedlist.cpp
#include"Linkedlist.h"
#include"btree.h"
#include<iostream>
using namespace std;
LinkedList::LinkedList() {
length = 0;
head = NULL;
}
//copy constructors.
LinkedList::LinkedList(LinkedList& other) {
length = 0;
if (this->head == other.head)
return;
Node* tmp = other.head;
while (tmp != NULL)
{
this->addToTail(tmp->data);
tmp = tmp->next;
}
length = other.length;
}
LinkedList::LinkedList(const LinkedList& other) {
this->length = other.length;
if (length == 0)
return;
Node* tmp = other.head;
while (tmp != NULL)
{
this->add(tmp->data);
tmp = tmp->next;
}
}
//destructor.
LinkedList::~LinkedList() {
Node* next = head;
Node* cur = NULL;
while (next != NULL) {
cur = next;
next = next->next;
delete cur;
}
}
//copying binary tree to a list.
LinkedList::LinkedList(btree &bt) {
if (bt.root == NULL)
this->head = NULL;
else
copyBtToList(bt.root);
}
void LinkedList::copyBtToList(node *bt)
{
node* tmp = bt;
if (!tmp)
return;
copyBtToList(tmp->left);
add(tmp->key_value);
copyBtToList(tmp->right);
}
//adding node to the head of the list.
void LinkedList::add(int data) {
Node* node = new Node();
node->data = data;
if (head == NULL) { //list is empty
head = node;
head->next = NULL;
length++;
return;
}
node->next = head;
head = node;
length++;
}
//adding node to the tail of the list.
void LinkedList::addToTail(int data) {
Node* node = new Node();
node->data = data;
node->next = NULL;
if (this->length == 0 || head == NULL) { //list is empty
head = node;
length++;
return;
}
Node* curr = head;
while (curr != NULL && curr->next!=NULL)
curr = curr->next;
curr->next = node;
length++;
}
//copying lists using "=" operator.
LinkedList & LinkedList::operator=(const LinkedList & bt)
{
LinkedList tmp(bt);
std::swap(tmp.head, this->head);
return *this;
}
//copying binary tree to list using "=" operator.
LinkedList & LinkedList::operator=(const btree & bt)
{
LinkedList tmp;
tmp.copyBtToList(bt.root);
head = tmp.head;
return *this;
}
//printing list in the form of "(x1,x2,...,xn)" using "<<" operator.
ostream & operator<<(ostream & os, LinkedList & l)
{
Node *tmp = l.head;
os << "List: (";
while (tmp != NULL)
{
os << tmp->data << ",";
tmp = tmp->next;
}
os << ")"<<endl;
return os;
}
main.cpp
#include"Linkedlist.h"
#include"btree.h"
#include<iostream>
using namespace std;
int main()
{
btree *tree = new btree();
tree->insert(10);
tree->insert(6);
tree->insert(14);
tree->insert(5);
tree->insert(8);
tree->insert(12);
tree->insert(16);
LinkedList* l = tree->Tree2linkListbyDepth();
int dp = tree->getTreeDepth();
for (int i = 0; i < dp; i++) {
cout << l[i];
}
cout << *tree;
tree->mirror();
cout << *tree;
btree *tree1 = new btree(l[dp - 1]);
cout << *tree1;
btree *tree2 = new btree(*tree1);;
tree2->insert(100);
cout << *tree1;
cout << *tree2;
LinkedList* l1 = new LinkedList(*tree1);
LinkedList* l2 = new LinkedList(*l1);
l2->add(99);
cout << *l1;
cout << *l2;
delete tree;
}
my output on VS:
List: (10,)
List: (14,6,)
List: (16,12,8,5,)
Tree: 5,6,8,10,12,14,16,
Tree: 16,14,12,10,8,6,5,
Tree: 5,8,12,16,
Tree: 5,8,12,16,
Tree: 5,8,12,16,100,
List: (16,12,8,5,)
List: (99,16,12,8,5,)
btw - i'll be happy if you could also check if my "includes" was done correctly cause i couldn't figure it out so easily...
Thanks :)
Update:
I ran your code through AppVerifier. And it didn't initially find anything until I tried different variations of Debug/Release x86/x64 builds. And one point I got it to crash in Windows. And then it stopped reproing the crash. Then I changed all your initial tree->insert statements to take a rand() value instead of a fixed value, I could get it to crash 100% of the time in Windows. I'm not sure if I event needed AppVerifier, but I left it on. That's when I noticed your LinkedList destructor was attempting to delete a pointer at 0xcccccccc, which is uninitialized memory in a debug build.
Bottom line, here is your bug:
Your LinkedList copy constructor is not initializing the head pointer to NULL
Also, you have two copy constructors. One that takes a non-const reference and is public. And another one (with slightly different behavior) that takes a const reference, but is private.
You just want a single copy constructor that is both public and takes a const reference.
Here's the fix. Let this be the public constructor:
LinkedList::LinkedList(const LinkedList& other) {
length = 0;
head = NULL; // YOU FORGOT THIS LINE
Node* tmp = other.head;
while (tmp != NULL)
{
this->addToTail(tmp->data);
tmp = tmp->next;
}
length = other.length;
}
And then remove the other instance of the LinkedList copy constructor.
Another thing that looks suspicious. Your btree constructor that takes a linked list is corrupting your list. It's also forgetting to initialize the object before attempting the first insert.
btree::btree(LinkedList &list)
{
while (list.head != NULL)
{
insert(list.head->data);
list.head = list.head->next;
}
}
This is completely wrong. When you construct the btree from the list (being passed via reference), the constructor will modify the passed in LinkedList instance. When this constructor returns, the list instance will be returned to the call with a null head pointer, but a non-zero length member when the function returns.. And your LinkedList destructor will not be able to recurse the tree to free the memory. So you have both a memory leak and an invalid object state.
Do this instead.
btree::btree(const LinkedList &list)
{
root = NULL;
isMirrored = false;
Node* tmp = list.head;
while (tmp != NULL)
{
insert(tmp->data);
tmp = tmp->next;
}
}
It's also better to use initializer lists with constructors:
btree::btree(const LinkedList &list) :
root(NULL),
isMirrored(false)
{
...
}
You are welcome :)
old stuff:
Your cout statements are missing an end-of-line marker (which flushes the output):
Instead of statements like this:
cout << *tree;
Do this:
cout << *tree << endl;
But that's not your issue. You have a crash in your program:
[ec2-user#ip-172-31-10-108 stackover]$ g++ main.cpp btree.cpp LinkedList.cpp
[ec2-user#ip-172-31-10-108 stackover]$ ./a.out
List: (10,)
List: (14,6,)
List: (16,12,8,5,)
Tree: 5,6,8,10,12,14,16,
Tree: 16,14,12,10,8,6,5,
Segmentation fault
Looks like we have a bug that results in a crash. Let's compile with a debug build and analyze:
[ec2-user#ip-172-31-10-108 stackover]$ g++ main.cpp btree.cpp LinkedList.cpp -g
[ec2-user#ip-172-31-10-108 stackover]$ gdb ./a.out
GNU gdb (GDB) Amazon Linux (7.6.1-64.33.amzn1)
...
Reading symbols from /home/ec2-user/stackover/a.out...done.
(gdb) run
Starting program: /home/ec2-user/stackover/./a.out
Missing separate debuginfo for /usr/lib64/libstdc++.so.6
Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/87/91ddd49348603cd50b74652c5b25354d8fd06e.debug
Missing separate debuginfo for /lib64/libgcc_s.so.1
Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/a0/3c9a80e995ed5f43077ab754a258fa0e34c3cd.debug
List: (10,)
List: (14,6,)
List: (16,12,8,5,)
Tree: 5,6,8,10,12,14,16,
Tree: 16,14,12,10,8,6,5,
Program received signal SIGSEGV, Segmentation fault.
0x00000000004011b5 in btree::mirrorInsert (this=0x614ea0, tmp=0x21, key=16) at btree.cpp:133
133 if (tmp->key_value <= key)
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.173.amzn1.x86_64
(gdb)
Short answer: it looks like you got some additional debugging to do around line 133 of btree.cpp. The value of tmp has a value of 0x21 - which is likely not a legitimate pointer value.

Circular Doubly Linked List C++

The removeNode() function implements a circular doubly linked list which has a sentinel node. What I am trying to do is defined in pseudo code next to the function. I simply just am having a hard time understanding how to do so.
#include "CDLList.h"
#include <iostream>
using namespace std;
ListNode *createList()
{
ListNode *sentinel = new ListNode();
sentinel->last = sentinel;
sentinel->next = sentinel;
return sentinel;
}
void destroyList(ListNode *&sentinel)
{
// Delete any item nodes
clearList(sentinel);
// Delete the sentinel node
delete sentinel;
sentinel = nullptr;
}
bool isEmpty(ListNode *sentinel)
{
return (sentinel == sentinel->next);
}
ListNode *findNode(ListNode *sentinel, string value)
{
ListNode *pCurrNode = sentinel->next;
while (pCurrNode != sentinel)
{
// Check if we found the node
if (pCurrNode->item == value)
{
return pCurrNode;
}
// Move to next node
pCurrNode = pCurrNode->next;
}
return nullptr;
}
void addItem(ListNode *sentinel, string value)
{
ListNode *newNode = new ListNode;
newNode->item = value;
newNode->last = sentinel->last;
newNode->next = sentinel;
sentinel->last->next = newNode;
sentinel->last = newNode;
}
void removeNode(ListNode *node) // Implement this function!
{
// Unlink node
// Delete node
}
The removeNode() function is called within these two functions
void removeItem(ListNode *sentinel, string value)
{
ListNode *node = findNode(sentinel, value);
// If the item was not found, there's nothing to do (remove)
if (node == nullptr)
{
return;
}
removeNode(node);
}
void clearList(ListNode *sentinel)
{
while (!isEmpty(sentinel))
{
removeNode(sentinel->next);
}
}
Here's the function implementation:
void removeNode(ListNode *node)
{
if(!isEmpty(node))
{
ListNode* nodeLast = node->last;
ListNode* nodeNext = node->next;
// Unlink node
nodeLast->next = nodeNext;
nodeNext->last = nodeLast;
}
// Delete node
delete node;
}

Trouble removing from linked list in C++

I have a function that removes from a linked list. Each node in the linked list is a dynamically created struct. To remove, I pass a data value in that I would like to search for in the list of nodes. If one of those nodes contains that data, I want to remove the entire node containing that data. It appears like they get added fine, but whenever I remove, the size variable decrements but the nodes are still in the list.
In Mag.h:
struct ListNode
{
int* data;
ListNode* nextNode;
};
class Mag
{
private:
ListNode* head;
public:
Mag();
Mag(Mag& mag);
Mag &operator= (const Mag &);
~Mag();
int size;
void add(const int&);
void remove(const int&);
void printList();
};
}
I add nodes to the list like this:
// adds to front of list
void Mag::add(int const &num)
{
Node* new_data = new ListNode();
new_data->data = num;
new_data->next = head;
head = newNode;
size++;
}
Now here's how I remove them (probably the issue):
void Mag::remove(int const &num)
{
if (head == NULL)
return;
int look_for = num;
ListNode* searchFor = head;
int count = 0;
count = size;
if (count != 0)
{
do
{
if (searchFor->data == look_for)
{
ListNode* delete_node = new ListNode;
delete_node = searchFor;
searchFor = searchFor->next;
size--;
delete delete_node;
return;
}
searchFor = searchFor->next;
count--;
} while (count != 0);
}
}

Trouble Connecting Two C++ Files (List.cc and Queue.cc)

I have to write a Queue in C++ using a List file that I created earlier and I'm having a rough time getting everything to compile.
The issue I am currently having is that when I compile I get the error:
Queue.h:7:2: error: 'List' does not name a type
How do I go about properly connecting my Queue file and my List file?
Here are the files I am using:
List.h
//an item in the list
struct ListNode {
int _value;
ListNode * _next;
};
class List {
public:
//Head of list
ListNode * _head;
int remove_front();
void insertSorted( int val );
void append (int val);
void prepend (int val);
int lookup( int _value );
int remove( int val );
void print();
List();
~List();
};
List.cc
//
// Implement the List class
//
#include <stdio.h>
#include "List.h"
ListNode * _head = new ListNode();
//remove the first node in the list
int
List::remove_front(){
int ret;
if(_head == 0){
return -1;
}
ret = _head->_value;
ListNode *temp = new ListNode();
temp = _head->_next;
delete(_head);
_head = temp;
return ret;
}
//
// Inserts a new element with value "val" in
// ascending order.
//
void
List::insertSorted( int val ){
ListNode* new_node = new ListNode();
new_node->_value = val;
ListNode* current = new ListNode();
if(_head == 0){
_head = new_node;
}else{
current = _head;
ListNode* prev = 0;
while(current != 0){
if(new_node->_value > current->_value){
prev = current;
current = current->_next;
}else{
break;
}
}
if(current == _head){
new_node->_next = _head;
_head = new_node;
}else{
new_node->_next = current;
prev->_next = new_node;
}
}
}
//
// Inserts a new element with value "val" at
// the end of the list.
//
void
List::append( int val ){
//create a new node to hold the given value
ListNode *new_node = new ListNode();
new_node->_value = val;
//if the list is empty
if(_head == 0){
//set the new node to be the head
_head = new_node;
return ;
}
//create a node pointer to the current position (starting at the head)
ListNode *current = new ListNode();
current = _head;
//Loop through the list until we find the end
while(current->_next != NULL){
current = current->_next;
}
current->_next = new_node;
}
//
// Inserts a new element with value "val" at
// the beginning of the list.
//
void
List::prepend( int val ){
ListNode *new_node = new ListNode;
new_node->_value = val;
if(_head == 0){
_head = new_node;
return ;
}
ListNode *temp = new ListNode;
temp = _head;
_head = new_node;
_head->_next = temp;
}
// Removes an element with value "val" from List
// Returns 0 if succeeds or -1 if it fails
int
List:: remove( int val ){
if(_head == 0){
printf("List is already empty.\n");
return -1;
}
ListNode *current = new ListNode();
ListNode* prev = new ListNode();
current = _head;
while(current != 0){
if(current->_value == val){
if(current == _head){
_head = _head->_next;
delete(current);
return 0;
}else{
prev->_next = current->_next;
delete(current);
return 0;
}
}else{
prev = current;
current = current->_next;
}
}
return -1;
}
// Prints The elements in the list.
void
List::print(){
ListNode* current = new ListNode();
while(current != 0){
printf("%d\n", current->_value);
current = current->_next;
}
}
//
// Returns 0 if "value" is in the list or -1 otherwise.
//
int
List::lookup(int val){
ListNode * current = new ListNode();
current = _head;
while(current != NULL){
if(current->_value == val){
return 0;
}
else{
current = current->_next;
}
}
return -1;
}
//
// List constructor
//
List::List(){
}
//
// List destructor: delete all list elements, if any.
//
List::~List(){
ListNode* current = _head;
while(current != NULL){
ListNode* next = current->_next;
delete current;
current = next;
}
}
Queue.h
#ifndef LIST_H
#define LIST_H
class Queue {
public:
List* queue_list;
void enqueue(int val);
int dequeue();
Queue();
~Queue();
};
#endif
Queue.cc
#include <stdio.h>
#include "List.h"
#include "Queue.h"
List *queue_list = new List();
void
Queue::enqueue(int val){
this->queue_list->prepend(val);
}
int
Queue::dequeue(){
int value = this->queue_list->remove_front();
return value;
}
Queue::Queue(){
//do nothing
}
Queue::~Queue(){
}
queue_main.cc
#include <stdio.h>
#include "Queue.h"
#include "List.h"
Queue *queue;
int main(){
}
Thanks for the help!
The compiler tells you what's wrong:
Queue.h:7:2: error: 'List' does not name a type
While reading Queue.h, the compiler cannot possibly know what List is, as there is nothing in this file that defines it.
You simply have to add a forward declaration:
#ifndef LIST_H
#define LIST_H
class List; // this is a forward declaration.
class Queue {
public:
List* queue_list;
void enqueue(int val);
int dequeue();
Queue();
~Queue();
};
#endif
Alternatively (but not necessary here), you could simply #include List.h. The rule of thumb is: Use forward declaration if possible. If the compiler complains about it, replace it by the corresponding include. The include is only necessary if the compiler must know the size of the class / struct.