Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I want to know proper way of destructing this code as I'm facing many random issues. However, this piece of code is working as I'm calling ~CacheFrame() first and than assinging nullptr to pageMap inside ~LruCache()
#include <iostream>
#include <unordered_map>
#include <list>
using namespace std;
struct Node {
int pageNumber;
Node *next;
Node *prev;
Node(int pageNumber, Node *prev, Node *next) {
this->pageNumber = pageNumber;
this->next = next;
this->prev = prev;
}
};
class CacheFrame {
const size_t maxSize;
int size;
Node *head, *tail;
public:
CacheFrame(int maxSize) : maxSize(maxSize) {
size = 0;
head = tail = nullptr;
}
~CacheFrame() {
cout << "CacheFrame Destructor called" << endl;
tail = nullptr;
while (head) {
Node *temp = head->next;
head->next = nullptr;
head->prev = nullptr;
delete head;
head = temp;
}
}
void MovePageToFront(Node* page) {
if (page == nullptr || page == head) {
return;
}
if (page == tail) {// point tail to second last element
tail = tail->prev;
tail->next = nullptr;
}
page->prev->next = page->next;
if (page->next)
page->next->prev = page->prev;
page->next = head;
head->prev = page;
head = page;
}
Node* InsertPage(int pageNumber) {
Node *page = new Node(pageNumber, nullptr, nullptr);
if (!head) {
head = tail = page;
size = 1;
return head;
}
if (size < maxSize) {
size++;
} else {
Node *temp = tail;
tail = tail->prev;
tail->next = nullptr;
delete temp;
}
page->next = head;
head->prev = page;
head = page;
return page;
}
size_t getCurrentSize() {
return size;
}
size_t getMaxSize() {
return maxSize;
}
int getLastPageNumber() {
return tail->pageNumber;
}
void printFrame() {
Node *start = head;
cout << "Frame" << endl;
while (start) {
cout << "-----" << endl;
cout << "| " << start->pageNumber << " |" << endl;
start = start->next;
}
cout << "-----"<< endl;
}
};
class LruCache {
const size_t size;
CacheFrame frame;
unordered_map<int, Node*> pageMap;
public:
LruCache(int size): size(size), frame(CacheFrame(size)) {}
~LruCache() {
cout << "LruCache Destructor called" << endl;
frame.~CacheFrame();
for (auto it: pageMap) {
cout << "Deleting " << it.first << " from map" << endl;
it.second = nullptr;
pageMap.erase(it.first);
// if (it.second) {
// it.second->next = nullptr;
// it.second->prev = nullptr;
// delete it.second;
// }
}
}
void accessPage(int pageNumber) {
cout << "Access Page : " << pageNumber << endl;
if (pageMap.find(pageNumber) != pageMap.end()) {// page hit
cout << "Page Hit" << endl;
frame.MovePageToFront(pageMap[pageNumber]);
} else {//page miss
cout << "Page Miss" << endl;
if (frame.getMaxSize() == frame.getCurrentSize()) {
pageMap.erase(frame.getLastPageNumber());
}
pageMap[pageNumber] = frame.InsertPage(pageNumber);
}
frame.printFrame();
}
};
int main() {
LruCache cache = LruCache(3);
int array[] = {4,2,1,1,4,3,7,8,3};
for (auto it: array) {
cache.accessPage(it);
}
return 0;
}
C++: What is best way to destruct this code?
You mean to free resources.
In case of unordered_map
The way to do it right is not to do it. A unordered_map will automatically release resources when it's destroyed for anything allocated automatically.
Unless you allocated the values with new, you don't delete them.
In case of linked list
~CacheFrame()
{
Node *temp = head->next, *temp2;
while(temp != NULL)
{
temp2 = temp;
temp = temp->next;
delete temp2;
}
}
Related
I have a program in which I'm supposed to build functions using linked lists to perform a variety of tasks. Currently, I am having an issue finding the min and max value of the linked list. For some reason when both come out to be the highest which digit which is 9, and when I try to find the average of the list, it still comes out as 9.
additionally, I think it's interfering with my pop function which is supposed to delete the last item, but when I try to work it by sections one part wont work until he previous section is running for whatever reason.
here is my header
#include <iostream>
using std::cout;
using std::endl;
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
class LinkedList
{
private:
struct Node
{
int data;
Node *next;
};
int size;
Node *head, *tail;
public:
LinkedList();
~LinkedList();
// misc
void display();
// sorting and searching
// reverse --> sorting in descending
int linearSearch(int key);
void sort();
void reverse();
// various math
int min();
int max();
int mean();
// adding
void append(int num);
void insert(int num, int pos);
// removing
void pop();
void remove(int pos);
};
#endif // LINKEDLIST_H
the header's source file
#include "linkedlist.h"
LinkedList::LinkedList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LinkedList::~LinkedList()
{
if(head != nullptr)
{
Node *temp;
while(head != nullptr)
{
temp = head->next;
// deletes head
delete head;
// goes to next element
head = temp;
}
}
}
void LinkedList::display()
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
cout << temp->data << "\t";
temp = temp->next;
}
cout << endl;
}
void LinkedList::append(int num)
{
// list is empty
if(head == nullptr)
{
head = new Node;
head->data = num;
head->next = nullptr;
// sets tail to head
tail = head;
}
else
{
// creates new node
Node *temp = new Node;
// sets new node data
temp->data = num;
temp->next = nullptr;
// sets previous tail link to new node
tail->next = temp;
// sets this node to new tail
tail = temp;
}
// increments size
size++;
}
void LinkedList::pop()
{
if(size > 1)
{
Node *temp = head;
// loops to node before tail
while(temp->next->next != nullptr)
{
temp = temp->next;
}
// deletes tail
delete tail;
// sets new tail
tail = temp;
tail->next = nullptr;
}
// if there's only one item
else if(size == 1)
{
Node *temp = tail;
// head and tail are now null
head = nullptr;
tail = nullptr;
// deletes node
delete temp;
}
size--;
}
void LinkedList::insert(int num, int pos)
{
if(pos ==0)
{
Node *temp=new Node;
temp->data=num;
temp->next=head;
head=temp;
}
if(pos>1)
{
Node *pre=new Node;
Node *cur=new Node;
Node *temp=new Node;
cur=head;
for(int i=1;i<pos+1;i++)
{
pre=cur;
cur=cur->next;
}
temp->data=num;
pre->next=temp;
temp->next=cur;
}
size++;
}
int LinkedList::linearSearch(int key)
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
if(temp->data == key)
{
return i;
}
temp = temp->next;
}
return -1;
}
int LinkedList::max()
{
int max = INT_MIN;
for(int i = 0; i < size; i++)
{
while (head != NULL)
{
if (head->data < max)
max = head->data;
head = head->next;
}
}
}
int LinkedList::min()
{
int min = INT_MAX;
for(int i = 0; i < size; i++)
{
while (head != NULL)
{
if (head->data < min)
min = head->data;
head = head->next;
}
}
}
void LinkedList::reverse()
{
Node* temp = head;
// Traverse the List
while (temp) {
Node* min = temp;
Node* r = temp->next;
// Traverse the unsorted sublist
while (r)
{
if (min->data < r->data)
min = r;
r = r->next;
}
// Swap Data
int x = temp->data;
temp->data = min->data;
min->data = x;
temp = temp->next;
}
}
void LinkedList::remove(int pos)
{
Node *temp = head;
if(pos ==0)
{
head = temp->next;
free(temp);
}
if(pos>1)
{
for(int i=0; temp!=NULL && i<pos-1;i++)
{
temp=temp->next;
}
temp->next = temp->next->next;
free(temp->next);
temp->next = temp->next;
}
size--;
}
int LinkedList::mean()
{
int sum = 0;
float avg = 0.0;
Node *temp = head;
while (head != NULL)
{
sum += temp->data;
temp = temp->next;
}
// calculate average
avg = (double)sum / size;
}
void LinkedList::sort()
{
Node* temp = head;
// Traverse the List
while (temp) {
Node* min = temp;
Node* r = temp->next;
// Traverse the unsorted sublist
while (r) {
if (min->data > r->data)
min = r;
r = r->next;
}
// Swap Data
int x = temp->data;
temp->data = min->data;
min->data = x;
temp = temp->next;
}
}
And the main
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main()
{
LinkedList nums;
// adding through append
nums.append(8);
nums.append(6);
nums.append(7);
nums.append(8);
nums.append(0);
nums.append(9);
// displays list
cout << "List after append: " << endl;
nums.display();
cout << endl;
// adding through insert
nums.insert(1, 0);
nums.insert(5, 4);
nums.insert(3, 8);
// displays list
cout << "List after inserting: " << endl;
nums.display();
cout << endl;
// testing searching
cout << "Testing linear search:" << endl;
int pres = nums.linearSearch(7);
if(pres < 0)
{
cout << "7 is not present in the list." << endl;
}
else
{
cout << "7 can be found at location " << pres << endl;
}
pres = nums.linearSearch(5);
if(pres < 0)
{
cout << "5 is not present in the list." << endl;
}
else
{
cout << "5 can be found at location " << pres << endl;
}
cout << endl;
// does math
cout << "Minimum, maximum, and average before removing any items: " << endl;
cout << "Min: " << nums.min() << endl;
cout << "Max: " << nums.max() << endl;
cout << "Mean: " << nums.mean() << endl << endl;
// displays items reversed
cout << "Items reversed: " << endl;
nums.reverse();
nums.display();
cout << endl;
// removing through pop
nums.pop();
nums.pop();
// displays list
cout << "List after popping: " << endl;
nums.display();
cout << endl;
// removing through remove
nums.remove(0);
nums.remove(2);
nums.remove(4);
// displays list
cout << "List after removing: " << endl;
nums.display();
cout << endl;
// displays items sorted
cout << "Items sorted: " << endl;
nums.sort();
nums.display();
cout << endl;
// does math
cout << "Minimum, maximum, and average after removing items: " << endl;
cout << "Min: " << nums.min() << endl;
cout << "Max: " << nums.max() << endl;
cout << "Mean: " << nums.mean() << endl << endl;
// testing searching
cout << "Testing linear search:" << endl;
pres = nums.linearSearch(7);
if(pres < 0)
{
cout << "7 is not present in the list." << endl;
}
else
{
cout << "7 can be found at location " << pres << endl;
}
pres = nums.linearSearch(5);
if(pres < 0)
{
cout << "5 is not present in the list." << endl;
}
else
{
cout << "5 can be found at location " << pres << endl;
}
return 0;
}
the only parts I'm really struggling with is the max, min, and mean along with getting my pop function to actually initiate. I know that the pop function is written correctly but ever since I made the max and min it wont work now.
There are several bugs that I have found in the code, and I have several remarks about it:
You should use spaces, and more consistently. There are places without enough spacing, and places with too many blank lines!
If you have two functions such as insert and append or pop and remove, they should use each other, meaning, append is just insert(0) (notice how I changed it in the code).
You are using double loops where it doesn't make sense (it isn't an error, but it is a bug!).
In the function max, you were doing the wrong comparison, asking if max is bigger than the current value...
You never return a value from min and max, which should at least create a warning in the compilation process!
You were creating empty nodes, and then you just put different values in their pointers, meaning that this new memory was still allocated (since there was no delete), but there was no way to access these anymore (this is a memory leak).
The biggest bug of all - When you loop in the min and max functions, you change the head of the list, which is a major bug (and that is why you got bugs after using this function). The solution is a simple but important lesson in C++ - Const Correctness.
What is const correctness, and why is it important?
When you have a function, that does not change the state of your object, it should be declared const. This is our way to tell the compiler (and other programmers) that it mustn't change the state of our object. For example, min, max and average are classic const functions - they simply make a calculation that does not change the list, and return. If you had written const in the declaration of those, the compilation would have failed, since you actually changed the list (changing the head), although you shouldn't!
Moreover, when receiving objects into a function, whenever possible, you should make the const T& where T is a type. They will enforce that you are using only const functions of this type.
Also, I suggest compiling (at least on g++) with the flags -Wpedantic -Werror'. The first adds some warnings about ISO C++ standards and the second makes all warnings into errors (and thus, yourmin,maxandmean` should not compile, since they don't return a value).
Here is the code:
class LinkedList
{
private:
struct Node
{
int data;
Node *next;
Node(int data_, Node* next_ = nullptr) :
data(data_),
next(next_)
{
}
};
int size;
Node *head, *tail;
public:
LinkedList();
~LinkedList();
void clear();
// various math
int min() const;
int max() const;
int average() const;
// adding
void append(int data);
void insert(int data, int pos);
// removing
void pop();
void remove(int pos);
};
LinkedList::LinkedList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LinkedList::~LinkedList()
{
clear();
}
void LinkedList::clear()
{
if (head != nullptr)
{
Node *temp;
while(head != nullptr)
{
temp = head->next;
delete head;
head = temp;
}
}
head = nullptr;
tail = nullptr;
size = 0;
}
void LinkedList::display()
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
std::cout << temp->data << "\t";
temp = temp->next;
}
std::cout << std::endl;
}
void LinkedList::insert(int data, int pos)
{
if (pos == 0)
{
Node* prev_head = head;
head = new Node(data, prev_head);
if (size == 0)
{
tail = head;
}
}
else
{
Node *pre=nullptr;
Node *cur = head;
for(int i = 0 ; i < pos + 1; ++i)
{
pre = cur;
cur = cur->next;
}
Node *temp = new Node(data, cur);
pre->next = temp;
}
++size;
}
void LinkedList::append(int data)
{
insert(data, 0);
}
void LinkedList::pop()
{
if (size == 1)
{
Node *temp = tail;
head = nullptr;
tail = nullptr;
delete temp;
}
else
{
Node *temp = head;
while(temp->next != tail)
{
temp = temp->next;
}
Node* node_to_pop = tail;
tail = temp;
tail->next = nullptr;
delete node_to_pop;
}
--size;
}
int LinkedList::max() const
{
int max = INT_MIN;
for (Node* temp = head; temp != nullptr; temp = temp->next)
{
if (temp->data > max)
{
max = temp->data;
}
}
return max;
}
int LinkedList::min() const
{
int min = INT_MAX;
for(Node* temp = head; temp != nullptr; temp = temp->next)
{
if (head->data < min)
{
min = temp->data;
}
}
return min;
}
int LinkedList::average() const
{
int sum = 0;
for(Node* temp = head; temp != nullptr; temp = temp->next)
{
sum += temp->data;
temp = temp->next;
}
return (double)sum / size;
}
Goal:
I've implemented a stack using a doubly linked list. I'm using a doubly linked list because the input size is 1 billion and using any other data structure will not render an optimal solution.
Problem:
I have two objects declared in the class MyStack() called root and tail. I want to initialize the values of these two objects to NULL initially. Later, when I call the push() method for the first time, it'll override the values of objects root and tail.
In my case, the code fails with an exception, “EXC_BAD_ACCESS (code=2, address=0x7fff5df48ff8) because the value of root is not NULL. I'm not sure where I should be initializing the values so that root and tail don't get overridden until push() is called.
The following is the .h file:
#ifndef UNTITLED_MYSTACK_H
#define UNTITLED_MYSTACK_H
class MyStack {
void* data;
MyStack* next;
MyStack* prev;
MyStack* root;
MyStack* tail;
public:
MyStack();
MyStack(void *data);
MyStack * newNode();
void *newNode(void* data);
bool isEmpty(MyStack *root);
void push(void *data);
void *pop();
int size();
virtual ~MyStack();
};
#endif //UNTITLED_MYSTACK_H
The following is the .cpp file
#include <iostream>
#include <climits>
#include <cstdlib>
#include "MyStack.h"
using namespace std;
MyStack::MyStack() : root(NULL), tail (NULL) {} // <-- ERROR here -->
MyStack::MyStack(void *data) : data(data) {} // <-- ERROR here -->
MyStack * MyStack::newNode()
{
MyStack* stackNode;
stackNode = new MyStack();
stackNode->data = NULL;
stackNode->next = NULL;
stackNode->prev = NULL;
return stackNode;
}
void* MyStack::newNode(void* data)
{
MyStack* stackNode;
stackNode = new MyStack(data);
stackNode->data = data;
stackNode->next = NULL;
stackNode->prev = NULL;
return stackNode;
}
bool MyStack::isEmpty(MyStack *root) {
return (root == NULL);
}
void MyStack::push(void *val) {
if (isEmpty(root)) {
root->data = newNode(val);
tail->data = newNode(val);
tail->next = newNode();
tail = tail->next;
root->next = tail;
tail->prev = root;
cout << " Element pushed to stack" << tail->data << endl;
}
else {
tail->data = val;
tail->next = newNode();
tail->next->prev = tail;
tail = tail->next;
cout << " Element pushed to stack" << tail->data << endl;
}
}
void *MyStack::pop() {
if (isEmpty(tail)) {
cout << "Stack is empty" << endl;
return NULL;
}
MyStack* evictedN = new MyStack();
evictedN = tail;
tail = tail->prev;
tail->next = newNode();
tail = tail->next;
return evictedN->data;
}
int MyStack::size() {
if(isEmpty(root)) {
cout << "Size is empty" << endl;
return 0;
}
int count = 1;
while (tail->prev != NULL) {
count += 1;
tail = tail->prev;
}
return count;
}
MyStack::~MyStack() {
}
//here is my main method
int main() {
MyStack s;
elem_t* elem;
elem->value = 10;
elem->other = 10 >> 1;
s.push(elem);
cout << elem->value << endl;
cout << elem->other << endl;
cout << s.pop() << endl;
cout << s.size() << endl;
return 0;
}
The main problem is that you are not distinguishing between the stack and the nodes that the stack contains. MyStack::newNode() is returning a completely new stack, not a new node. According to this code:
void MyStack::push(void *val) {
if (isEmpty(root)) {
root->data = newNode(val);
tail->data = newNode(val);
tail->next = newNode();
tail = tail->next;
root->next = tail;
tail->prev = root;
cout << " Element pushed to stack" << tail->data << endl;
}
else {
tail->data = val;
tail->next = newNode();
tail->next->prev = tail;
tail = tail->next;
cout << " Element pushed to stack" << tail->data << endl;
}
}
in the case where the root is NULL, isEmpty(root) returns true, so we go ahead and dereference it anyway by accessing root->data. This is undefined behavior.
You need to distinguish between a node and a stack and rewrite the code with that distinction in mind. elem_t could be the node type, or you could define a new class.
here is the MyStack_class.h file:
#ifndef MYSTACK_CLASS_H
#define MYSTACK_CLASS_H
class elem_t {
public:
int value;
int other;
elem_t() {};
elem_t(int value, int other) : value(value), other(other) {}
~elem_t() {};
};
class MyStack {
private:
void* data;
MyStack* next;
MyStack* prev;
public:
MyStack () {}
MyStack(void* val) : data(val), next(nullptr), prev(nullptr) {}
~MyStack() {}
MyStack* newNode();
MyStack* newNode(void*);
void push(void*);
void* pop();
int size();
};
#endif
~
The following is the MyStack_class.cpp file:
#include <iostream>
#include "MyStack_class.h"
#include <cstdlib>
using namespace std;
int count = 0;
MyStack* root = new MyStack();
MyStack* tail = new MyStack();;
MyStack* MyStack::newNode()
{
MyStack* stackNode;
stackNode = new MyStack();
stackNode->data = NULL;
stackNode->next = NULL;
stackNode->prev = NULL;
return stackNode;
}
MyStack* MyStack::newNode(void* data)
{
MyStack* stackNode;
stackNode = new MyStack(data);
stackNode->data = data;
stackNode->next = NULL;
stackNode->prev = NULL;
return stackNode;
}
void MyStack::push (void* val)
{
if (count == 0) {
root = newNode(val);
tail = newNode(val);
tail->next = newNode();
tail = tail->next;
root->next = tail;
tail->prev = root;
count++;
cout << "Element: " << count << " pushed to Stack" << endl;
}
else {
tail->data = val;
tail->next = newNode();
tail->next->prev = tail;
tail = tail->next;
count++;
cout << " Element " << count << " pushed to stack" << endl;
}
}
void* MyStack::pop()
{
if (count == 0) {
cout << "Stack is empty" << endl;
exit(1);
}
MyStack* evictedN = new MyStack();
tail = tail->prev;
evictedN = tail;
tail->next = tail->next->prev = NULL;
count--;
return evictedN->data;
}
int MyStack::size() {
int cnt = 0;
while(root->next != NULL) {
cnt++;
root = root->next;
}
return cnt;
}
The MyStack_class library is used in the following program which can be called
main.cpp or anything that you'd like:
#include <iostream>
#include <cstdlib>
#include "MyStack_class.h"
#define NELEM 1000
using namespace std;
void
example() {
MyStack* s = new MyStack;
for (int i = 0; i < NELEM; i++) {
elem_t* elem = new elem_t(i , i >> 1);
if (elem == NULL) {
exit(1);
}
s->push(elem);
cout << "the pushed element's value and other respectively : " << elem->value << " " << elem->other << endl;
}
cout << "Stack size : " << s->size() << endl;
for (int i = (NELEM-1); i > 0; i--) {
elem_t* elem = static_cast<struct elem_t*>(s->pop());
if (elem->value != i) {
cout << "Error: i is " << i << "and elem-value is " << elem->value << endl;
}
cout << "The popped element's value and other respectively: " << elem->value << " " << elem->other << endl;
delete elem;
}
delete s;
}
int
main()
{
example();
return 0;
}
Here's how my Makefile looks:
MyStack_class: MyStack_class.o main.o
g++ MyStack_class.o main.o -o MyStack_class
MyStack_class.o: MyStack_class.cpp main.cpp
g++ -c -std=c++0x MyStack_class.cpp main.cpp
clean:
rm MyStack_class.o main.o MyStack_class
I'm trying to implement a stack using a doubly linked list. I know that the functions for my stack class (push, pop) should contain calls to member functions of my doubly linked list class, but I'm having trouble actually implementing that.
dlist.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include "dlist.hpp"
using namespace std;
void dlist::appendNodeFront(int shares, float pps){
Node *n = new Node(shares, pps);
if(front == NULL){
front = n;
back = n;
}
else {
front->prev = n;
n->next = front;
front = n;
}
}
void dlist::appendNodeBack(int shares, float pps){
Node *n = new Node(shares, pps);
if(back == NULL){
front = n;
back = n;
}
else {
back->next = n;
n->prev = back;
back = n;
}
}
void dlist::display(){
Node *temp = front;
cout << "List contents: ";
while(temp != NULL){
cout << temp->value << " ";
temp = temp->next;
}
cout << endl;
}
void dlist::display_reverse(){
Node *temp = back;
cout << "List contents in reverse: ";
while(temp != NULL){
cout << temp->value << " ";
temp = temp->prev;
}
cout << endl;
}
void dlist::destroyList(){
Node *T = back;
while(T != NULL){
Node *T2 = T;
T = T->prev;
delete T2;
}
front = NULL;
back = NULL;
}
stack.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include "stack.hpp"
using namespace std;
stack::stack(){
int i;
for(i = 0; i < 1500; i++){
shares[i] = 0;
pps[i] = 0;
}
first = 0;
}
void stack::push(int num, float price){
if(first ==(1500-1)){
cout << "Stack is full" << endl;
return;
}
first++;
shares[first] = num;
pps[first] = price;
return;
}
void stack::pop(int *num, float *price){
if(first == -1){
cout << "Stack is empty" << endl;
return;
}
num = &shares[first];
price = &pps[first];
cout << shares[first] << endl;
cout << pps[first] << endl;
shares[first] = 0;
pps[first] = 0;
first--;
return;
}
Should the push function in stack basically be a call to appendNodeFront() or appendNodeback()? Any help or advice is greatly appreciated!
You can create a stack class, then use linked list class as its container. In a linked list class there is virtually no limit to the number of items, so you add artificial limit to make it work like a stack. In a linked list, items can be added/removed anywhere in the list, you can limit add/remove the tail node only to make it work like stack. The example below demonstrate the usage.
Node that this is purely a programming exercise. Stack is relatively primitive compared to Doubly-linked list. Encapsulating a linked-list inside stack has no advantage. Also note, I declared all members as public for the sake of simplifying the problem, you may want to change some members to protected/private
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
class Node
{
public:
Node *prev;
Node *next;
int shares;
float pps;
Node(int vshares, float vpps)
{
shares = vshares;
pps = vpps;
prev = next = nullptr;
}
};
class dlist
{
public:
Node *head;
Node *tail;
dlist()
{
head = tail = nullptr;
}
~dlist()
{
destroy();
}
void push_back(int shares, float pps)
{
Node *node = new Node(shares, pps);
if (head == NULL)
{
head = tail = node;
}
else
{
tail->next = node;
node->prev = tail;
tail = node;
}
}
void destroy()
{
Node *walk = head;
while (walk)
{
Node *node = walk;
walk = walk->next;
delete node;
}
head = tail = nullptr;
}
};
class stack
{
public:
int maxsize;
int count;
dlist list;
stack(int size)
{
count = 0;
maxsize = size;
}
void push(int num, float price)
{
if (count < maxsize)
{
list.push_back(num, price);
count++;
}
}
void pop()
{
Node *tail = list.tail;
if (!tail)
{
//already empty
return;
}
if (tail == list.head)
{
//only one element in the list
delete tail;
list.head = list.tail = nullptr;
count--;
}
else
{
Node *temp = list.tail->prev;
delete list.tail;
list.tail = temp;
list.tail->next = nullptr;
count--;
}
}
void display()
{
Node *walk = list.head;
while (walk)
{
cout << "(" << walk->shares << "," << walk->pps << ") ";
walk = walk->next;
}
cout << "\n";
}
};
int main()
{
stack s(3);
s.push(101, 0.25f);
s.push(102, 0.25f);
s.push(103, 0.25f);
s.push(104, 0.25f);
s.display();
s.pop();
s.display();
return 0;
}
I keep getting a Segmentation fault (core dumped) error every time I try to run my code with g++ on Linux. It compiles fine, but then that happens ... All the functions (remove, add and print) seem to have the same problem, I can't seem to figure out what's wrong... Please heeeelppp.
#include <iostream>
#include <string>
using namespace std;
//Create a node struct
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
//set to NULL
Queue::Queue() {
head = tail = NULL;
size = 0;
}
//destructor
//call remove until empty
Queue::~Queue() {
while (!isEmpty())
remove();
}
//adds a node with the given data at the back of the queue
void Queue::add(int d) {
Node *temp = new Node();
temp->data = d;
temp->next = NULL;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
//removes the node at the head of the queue and returns its data
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *temp = new Node;
temp = head;
int value = head->data;
//moves pointer to next node
head = head->next;
cout << "Removed: " << head->data << endl;
size--;
delete temp;
return value;
}
}
//determines if the queue is empty
bool Queue::isEmpty() {
return (size == 0);
}
//prints the contents of the queue from front to back, or front
//to back, depending on the value of the parameter
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p = new Node;
if (o == true) {
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
p = head;
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
p = tail;
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(8);
return 0;
}
EDIT: I've made some changes to the code... But I'm still getting the same error. I assume I'm not updating the head and the tail and/or the next and prev nodes correctly... I don't know why it's wrong or what I'm missing, though.
#include <iostream>
#include <string>
using namespace std;
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
Queue::Queue() {
head = tail = NULL;
size = 0;
}
Queue::~Queue() {
while (!isEmpty())
remove();
}
void Queue::add(int d) {
Node *temp = new Node;
temp->data = d;
temp->next = NULL;
temp->prev = tail;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
return 0;
} else {
Node *temp = head;
int value = head->data;
cout << "Removed: " << head->data << endl;
//moves pointer to next node
head = head->next;
head->prev = NULL;
size--;
delete temp;
return value;
}
}
bool Queue::isEmpty() {
return (size == 0);
}
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p;
if (o == true) {
p = head;
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
p = tail;
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(9);
q.add(10);
q.add(11);
q.add(12);
q.add(13);
q.add(14);
q.add(15);
q.add(16);
q.remove();
q.remove();
q.printQueue(true);
q.printQueue(false);
return 0;
}
Lots of problems:
You have a double-linked Node but never update its prev member in the add/remove methods.
You are keeping track of both the Queue head/tail but don't properly update them when you add/remove nodes.
Both your forward and reverse loops in printQueue() are wrong and result in an infinite loop for any queue with 2 or more elements. Queue output should be just something like:
Node *p = head;
while (p != NULL)
{
cout << p->data << " ";
p = p->next;
}
Possible null pointer deference in remove() at cout << "Removed: " << head->data << endl; since you've already moved the head pointer by this time. Move the head after the cout.
Memory leak in Queue::remove() at Node *temp = new Node;. Just do Node* temp = head;.
Memory leak in Queue::printQueue() at Node *p = new Node;. You don't need to allocate a node here.
No return value in remove() for an empty queue.
Edit
Don't forget to initialize the tail when adding a node to an empty list:
if (isEmpty()) {
head = temp;
tail = temp;
}
To remove a node from the head of a non-empty list it should be something like:
Node *temp = head;
head = head->next;
if (head) head->prev = NULL;
size--;
delete temp;
if (isEmpty()) tail = NULL;
I'm trying to make a dynamic queue in C++ and I wrote most of the code, yet it doesn't work, could someone be kind enough to look through it and tell me what's wrong? :)
Also please comment on the coding style I wish to improve.
I wrote a main function to test the program and this should be the expected result:
data1=1
data1=1 data2=2
1 2 3 4 5 6
Del:1 Del:2 Del:3
This is my code:
#include <iostream>
template<typename T>
class Queue
{
struct Node
{
T data;
Node* next;
};
Node* head;
Node* tail;
int qsize;
public:
Queue()
{
head = NULL;
tail = NULL;
qsize = 0;
}
bool empty()
{
if(qsize = 0){return true;}
else {return false;}
}
void put(const T& data)
{
Node *newNode = new Node;
if(qsize)
{
tail->next = newNode;
newNode->data = data;
newNode->next = NULL;
tail = newNode;
}
else
{
head = tail = newNode;
newNode->data = data;
newNode->next = NULL;
}
qsize++;
}
T get()
{
T val;
Node *temp;
if(empty())
{
std::cout << "queue is empty" << std::endl;
}
else
{
val = head->data;
temp = head;
head = head->next;
delete temp;
qsize--;
return val;
}
}
void destroyQueue()
{
while(!empty())
{
std::cout<<"DEL:";
get();
}
}
~Queue()
{
destroyQueue();
}
};
int main()
{
int data1,data2;
Queue<int>* q = new Queue<int>();
q->put(1);
data1 = q->get();
std::cout << " data1=" << data1 << std::endl;
q->put(1);
q->put(2);
data1 = q->get();
data2 = q->get();
std::cout << " data1=" << data1
<< " data2=" << data2 << std::endl;
q->put(1);
q->put(2);
q->put(3);
q->put(4);
q->put(5);
q->put(6);
while (!q->empty()) std::cout << " " << q->get();
std::cout << std::endl;
q->put(1);
q->put(2);
q->put(3);
delete q;
}
if(qsize = 0) should be if(qsize == 0) - don't assign, compare!