The following is a new programmer's attempt at a Queue. It seg faults in the Push() function, when I try to print the data in the first node. Looks like front_ptr is not actually getting set in head_insert. What am I doing wrong here, is this a completely wrong approach?
Thanks.
#include <cstdlib>
#include <iostream>
using namespace std;
class node {
public:
typedef double data_type;
node(data_type init_data = 0, node * init_next = NULL) {
data = init_data;
next_node = init_next;
}
void set_data(data_type new_data) { data = new_data; }
void set_next(node * new_next) { next_node = new_next; }
data_type get_data() { return data; }
node * get_next() { return next_node; }
private:
data_type data;
node * next_node;
};
void head_insert(node::data_type val, node* head_ptr) {
node* insert_ptr = new node(val, head_ptr);
head_ptr = insert_ptr;
}
void list_insert(node::data_type val, node* prev_ptr) {
node* insert_ptr = new node(val, prev_ptr->get_next());
prev_ptr->set_next(insert_ptr);
}
void head_remove(node* head_ptr) {
node* remove_ptr = head_ptr;
head_ptr = head_ptr->get_next();
delete remove_ptr;
}
void list_remove(node * prev_ptr) {
node* remove_ptr = prev_ptr->get_next();
prev_ptr->set_next(remove_ptr->get_next());
delete remove_ptr;
}
void list_clear(node* head_ptr) {
while (head_ptr != NULL) {
head_remove(head_ptr);
}
}
class queue {
public:
queue() {
size = 0;
front_ptr = NULL;
rear_ptr = NULL;
}
//~queue() {}
bool empty() { return (size == 0);}
void push(node::data_type val) {
if (empty()) {
head_insert(val, front_ptr);
cout << "Here: " << front_ptr->get_data() << endl;
rear_ptr = front_ptr;
}
else {
list_insert(val, rear_ptr);
}
size++;
}
void pop() {
if (!empty()) {
head_remove(front_ptr);
size--;
}
}
private:
node* front_ptr;
node* rear_ptr;
int size;
};
int main() {
cout << "START" << endl;
double testVal = 1;
queue* qList = new queue();
qList->push(testVal);
cout << "END" << endl;
return 0;
}
Any help is greatly appreciated.
Your front_ptr remains null pointer in push, because head_insert accepts it by value. Dereferencing null pointer then crashes the program. Make parameters that you want to be modified by a function reference parameters like void head_insert(node::data_type val, node*& head_ptr).
Also, you can avoid crash of null pointer dereferencing by checking it before, for example like that:
cout << "Here: " << (front_ptr ? front_ptr->get_data() : 0./0.) << endl;
Related
I implement a doubly linked list. Then I used that linked list as container for stack. but I get Error C2662 'const T &List::last_elem(void)': cannot convert 'this' pointer from 'const List' to 'List &'. I tried to return as a value but it didnt work. I dont understand whether compiler points wrong point.
template<typename T>
struct Node
{
T data;
Node* next;
Node* prev;
Node() :data{ 0 } { next = nullptr; prev = nullptr; }
};
template<typename T>
class List
{
private:
Node<T>* headNode;
Node<T>* tailNode;
public:
List()
{
headNode = new Node<T>;
tailNode = new Node<T>;
headNode->next = tailNode;
tailNode->prev = headNode;
}
~List()
{
Node<T>* current = headNode;
while (current)
{
Node<T>* tempNode = current;
current = current->next;
delete tempNode; cout << "\nDeleting List!!!";
}
}
bool empty()
{
return (headNode->next == tailNode);
}
const T &last_elem()
{
return tailNode->prev->data;
}
const T &first_elem()
{
return headNode->next->data;
}
void remove_first()
{
Node<T>* tempNode = headNode;
headNode = tempNode->next;
delete tempNode; cout << "\nDeleting Node!!!";
headNode->prev = nullptr;
}
void remove_last()
{
Node<T>* tempNode = tailNode;
tailNode = tempNode->prev;
delete tempNode; cout << "\nDeleting Node!!!";
tailNode->next = nullptr;
}
void add_front(T d)
{
headNode->data = d;
Node<T>* tempNode = new Node<T>;
tempNode->next = headNode;
headNode->prev = tempNode;
headNode = tempNode;
}
void add_end(T d)
{
tailNode->data = d;
Node<T>* tempNode = new Node<T>;
tempNode->prev = tailNode;
tailNode->next = tempNode;
tailNode = tempNode;
}
void print_list()
{
Node<T>* current = headNode->next;
while (current)
{
cout << current->data << "|-> ";
current = current->next;
}
}
void reverse_print_list()
{
Node<T>* current = tailNode->prev;
while (current)
{
cout << current->data << "|-> ";
current = current->prev;
}
}
};
template<typename T>
class ListStack
{
private:
List<T> stacklist;
int index;
public:
class StackException
{
private:
string errMessage;
public:
StackException(string err) :errMessage(err) {}
string getErrMessage() { return errMessage; }
};
ListStack():index { -1 }{}
int size() const // number of items in the stack
{
return index + 1;
}
bool empty() const // is the stack empty?
{
return (index == -1);
}
const T& top() const throw(StackException) // the top element
{
if (empty())throw StackException(string("Stack is empty!!!"));
return stacklist.last_elem();
}
void push(const T& e) // push element onto stack
{
stacklist.add_end(e);
++index;
}
void pop() throw(StackException) // pop the stack
{
if (empty())throw StackException(string("Stack is empty!!!"));
stacklist.remove_last();
--index;
}
};
int main()
{
try
{
ListStack<int> myls;
myls.push(5);
myls.push(8);
myls.push(9);
myls.push(12);
myls.push(17);
cout << myls.top() << endl;
myls.pop();
myls.pop();
myls.pop();
myls.pop();
myls.pop();
myls.pop();
myls.pop();
myls.pop();
myls.pop();
}
catch (ListStack<int>::StackException se)
{
cout << se.getErrMessage();
}
return 0;
}
Make last_elem() a const qualified with:
const T &last_elem() const
// ^^^^^
The Problem is:
const T& top() const throw(StackException)
remove the second const to
const T& top() throw(StackException)
And you should be fine.
(this is because the called last_elem() method is not const since constant methods can obviously not call non-constant methods, so making that one const would work too).
I am trying to run my linked list iterator to print the data I have entered into the list. It does manage to print all the entries, but as soon as it does, the program crashes. Does anyone see what might be causing it? I am running it on CodeBlocks so I don't know if that might be the problem.
It is the same project I've been dealing with in my other questions. Before I tried running the iterator to print the contents from the function inside the list class. However, the specs of the assignment don't allow the classes to trigger any error or control messaging within the report. The ideal is for the user to access the data completely. Anything like console messages have to be done in main. This is what I've gotten after tweaking it. Again, it prints the contents of the list successfully, but after that, the program stops working.
Code:
#include <iostream>
#include <string>
using namespace std;
typedef string dataType;
typedef class LISTEntry* listPtr;
class DATAClass
{
dataType key;
public:
DATAClass();
DATAClass(dataType key);
DATAClass(DATAClass &dc);
void setKey(dataType keyVal);
dataType getKey();
};
DATAClass::DATAClass() {
key = key;
}
DATAClass::DATAClass(dataType key) {
this->key = key;
}
DATAClass::DATAClass(DATAClass &dc) {
key = dc.key;
}
void DATAClass::setKey(dataType keyVal) {
key = keyVal;
}
dataType DATAClass::getKey() {
return key;
}
class LISTEntry
{
DATAClass data;
listPtr prev;
listPtr next;
public:
LISTEntry() {
this->data = data;
this->prev = nullptr;
this->next = nullptr;
};
LISTEntry(DATAClass l) {
this->data = l;
this->prev = nullptr;
this->next = nullptr;
};
LISTEntry(LISTEntry &le) {
data = le.getData();
prev = nullptr;
next = nullptr;
};
~LISTEntry() {
};
LISTEntry & operator=(const LISTEntry &le) {
if (this != &le)
{
data = le.data;
prev = nullptr;
next = nullptr;
}
};
LISTEntry * getNext() {
return next;
};
void setNext(LISTEntry * entry) {
next = entry;
};
LISTEntry * getPrev() {
return prev;
};
void setPrev(LISTEntry * entry) {
prev = entry;
};
DATAClass getData() {
return data;
};
void setData(DATAClass d) {
data = d;
};
};
class LIST
{
private:
listPtr curr;
listPtr head;
listPtr tail;
public:
LIST();
LIST(DATAClass d);
LIST(LISTEntry l);
LIST(LIST * l);
~LIST();
void addList(dataType n);
void iterateInitialize();
bool iterate_hasNext();
bool searchList(dataType key);
LISTEntry * getHead();
void setHead(LISTEntry * h);
LISTEntry * getTail();
void setTail(LISTEntry * t);
LISTEntry * getCurr();
void setCurr(LISTEntry * c);
bool isEmpty();
bool isFull();
};
LIST::LIST() {
curr = nullptr;
head = nullptr;
tail = nullptr;
};
LIST::LIST(DATAClass d) {
listPtr tmp;
tmp->setData(d);
tmp->getData();
curr = tmp;
head = nullptr;
tail = nullptr;
};
LIST::LIST(LISTEntry l) {
listPtr tmp;
curr = tmp;
head = tmp;
tail = tmp;
};
LIST::LIST(LIST * l) {
curr = nullptr;
head = nullptr;
tail = nullptr;
};
LIST::~LIST()
{}
void LIST::addList(dataType n) {
DATAClass dc;
dc.setKey(n);
listPtr entry = new LISTEntry();
entry->setData(dc);
entry->setNext(nullptr);
entry->setPrev(nullptr);
if (!isEmpty())
{
tail->setNext(entry);
entry->setPrev(tail);
tail = entry;
curr = tail;
curr->setNext(nullptr);
tail->setNext(nullptr);
}
else
{
head = tail = entry;
head->setPrev(nullptr);
tail->setNext(nullptr);
curr = head;
}
} //addList
void LIST::iterateInitialize() {
setCurr(head);
}
bool LIST::iterate_hasNext() {
return curr->getNext() != nullptr;
}
bool LIST::searchList(dataType key) {
curr = head;
while (curr != nullptr)
{
if (curr->getData().getKey() == key)
{
return true;
}
else
{
curr = curr->getNext();
}
}
return false;
}
LISTEntry * LIST::getHead() {
return head;
}
void LIST::setHead(LISTEntry * h) {
head = h;
}
LISTEntry * LIST::getTail() {
return tail;
}
void LIST::setTail(LISTEntry * t) {
tail = t;
}
LISTEntry * LIST::getCurr() {
return curr;
}
void LIST::setCurr(LISTEntry * c) {
curr = c;
}
bool LIST::isEmpty() {
return head == nullptr;
}
bool LIST::isFull() {
return (new(LISTEntry) == nullptr);
}
int main()
{
LIST * burger = new LIST();
burger->addList("meat");
burger->addList("pickles");
burger->addList("onions");
burger->addList("tomato");
burger->addList("cheese");
burger->addList("bun");
burger->iterateInitialize();
listPtr bgrIndex = burger->getCurr();
while (burger->iterate_hasNext())
{
cout << bgrIndex->getData().getKey() << " ";
bgrIndex = bgrIndex->getNext();
if (!(burger->iterate_hasNext()))
cout << endl;
}
dataType searchValue;
while (searchValue != "end")
{
cout << "Enter an item to look up in the list: " << endl;
cin >> searchValue;
if (burger->searchList(searchValue))
cout << "The item " << searchValue << " was found." << endl;
else
cout << "The item " << searchValue << " is not in the list." << endl;
}
delete burger;
return 0;
}
I'm trying to create a basic singly-linked list using a separate Node class and LinkedList class. I barely know what I'm doing as I've just started learning C++, so any help would be greatly appreciated.
The LinkedList part of the code runs on its own, but I'm sure there are some corrections to be made there too. My main problem is that, when trying to add to the linked list, I'm getting (at line 64 of LinkedList.h):
Exception thrown: read access violation. this->head was nullptr.
I'm using Microsoft Visual Studio 2015. Here's the code:
LinkedList.h (it's inline):
#pragma once
#include <iostream>
using namespace std;
class Node
{
private:
Node *next = NULL;
int data;
public:
Node(int newData) {
data = newData;
next = NULL;
}
Node() {
}
~Node() {
if(next)
delete(next);
}
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
void setNext(Node newNext) {
*next = newNext;
}
Node getNext() {
return *next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
{
head = NULL;
size = 0;
}
~LinkedList()
{
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, *head);
++size;
}
int remove()
{
if (size == 0) {
return 0;
}
else {
*head = (*head).getNext();
--size;
return 1;
}
}
int remove(int numberToRemove)
{
if (size == 0)
return 0;
Node *currentNode = head;
for (int i = 0; i < size; i++) {
if ((*currentNode).getData() == numberToRemove) {
*currentNode = (*currentNode).getNext();
return 1;
}
}
}
void print()
{
if (size == 0) {
return;
}
else {
Node currentNode = *head;
for (int i = 0; i < size; i++) {
cout << currentNode.getData();
currentNode = currentNode.getNext();
}
cout << endl;
}
}
};
List Tester.cpp
// List Tester.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "LinkedList.h"
using namespace std;
int main()
{
LinkedList myList;
myList.add(4);
system("pause");
}
You are making copies where you should not:
This:
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
should be:
Node(int newData, Node* newNext) {
data = newData;
next = newNext;
}
Because now this:
head = new Node(numberToAdd, *head);
becomes this:
head = new Node(numberToAdd, head);
and will work even if head is a null pointer. You may need to adjust your other code accordingly.
Your whole implementation is full of errors. It should look more like this instead:
#pragma once
#include <iostream>
class Node
{
private:
int data;
Node *next;
public:
Node(int newData, Node *newNext = NULL)
: data(newData), next(newNext)
{}
void setNext(Node *newNext) {
next = newNext;
}
Node* getNext() {
return next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
: head(NULL), size(0)
{
}
~LinkedList()
{
Node *currentNode = head;
while (currentNode)
{
Node *nextNode = currentNode->getNext();
delete currentNode;
currentNode = nextNode;
}
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, head);
++size;
}
bool remove()
{
Node *currentNode = head;
if (!currentNode)
return false;
head = currentNode->getNext();
delete currentNode;
--size;
return true;
}
bool remove(int numberToRemove)
{
Node *currentNode = head;
Node *previousNode = NULL;
while (currentNode)
{
if (currentNode->getData() == numberToRemove)
{
if (head == currentNode)
head = currentNode->getNext();
if (previousNode)
previousNode->setNext(currentNode->getNext());
delete currentNode;
return true;
}
previousNode = currentNode;
currentNode = currentNode->getNext();
}
return false;
}
void print()
{
Node *currentNode = head;
if (!currentNode) return;
do
{
std::cout << currentNode->getData();
currentNode = currentNode->getNext();
}
while (currentNode);
std::cout << std::endl;
}
};
Which can then be simplified using the std::forward_list class (if you are using C++11 or later):
#pragma once
#include <iostream>
#include <forward_list>
#include <algorithm>
class LinkedList
{
private:
std::forward_list<int> list;
public:
void add(int numberToAdd)
{
list.push_front(numberToAdd);
}
bool remove()
{
if (!list.empty())
{
list.pop_front();
return true;
}
return false;
}
bool remove(int numberToRemove)
{
std::forward_list<int>::iterator iter = list.begin();
std::forward_list<int>::iterator previous = list.before_begin();
while (iter != list.end())
{
if (*iter == numberToRemove)
{
list.erase_after(previous);
return true;
}
++previous;
++iter;
}
return false;
}
void print()
{
if (list.empty()) return;
std::for_each(list.cbegin(), list.cend(), [](int data){ std::cout << data });
std::cout << std::endl;
}
};
I have the following code. It creates a binary tree class. The functions are insert(), pre_order(), post_order(), in_order(). But when I debug it I get zeros values. Also I insert 9 values but only have 7 zeros. Why I did wrong?
#include <iostream>
using namespace std;
//Begin the construction of the BINARY TREE
struct tree_node {
tree_node *left;
tree_node *right;
int data;
};
//Declaring the class
class bst {
tree_node *root; //creating the root of the binary tree
public:
bst() {
root = NULL; //intialize the default construction, set the root to NULL
}
int is_empty() { //check for empty graph
return (root == NULL);
}
//Manipulating the Binary Tree
void insert(int item);
void remove_it(int value); //difficult implementation
//Graph Traversal of Binary Tree
void in_order_trav();
void in_order(tree_node *);
void pre_order_trav();
void pre_order(tree_node *);
void post_order_trav();
void post_order(tree_node *);
};
void bst::insert(int item) {
tree_node *p = new tree_node;
tree_node *parent;
p->left = NULL;
p->right = NULL;
parent = NULL;
if (is_empty()) {
root = p;
}
else {
tree_node *ptr;
ptr = root;
while (ptr != NULL) {
parent = ptr;
if (item > ptr->data)
ptr = ptr->right;
else
ptr = ptr->left;
}
if (item < parent->data)
parent->left = p;
else
parent->right = p;
}
}
/*************In Order Traversal*****************************/
// Begin
void bst::in_order_trav() {
in_order(root);
}
void bst::in_order(tree_node *ptr) {
if (ptr!=NULL) {
in_order(ptr->left);
cout << " " << ptr->data << " ";
in_order(ptr->right);
}
}
// End
/***********************************************************/
/*************Pre Order Traversal*****************************/
// Begin
void bst::pre_order_trav() {
pre_order(root);
}
void bst::pre_order(tree_node *ptr) {
if (ptr!=NULL) {
cout << " " << ptr->data << " ";
pre_order(ptr->left);
pre_order(ptr->right);
}
}
// End
/***********************************************************/
/*************Post Order Traversal*****************************/
// Begin
void bst::post_order_trav() {
post_order(root);
}
void bst::post_order(tree_node *ptr) {
if(ptr!=NULL) {
post_order(ptr->left);
post_order(ptr->right);
cout << " " << ptr->data << " ";
}
}
// End
/***********************************************************/
int main() {
bst bin_tree; //create the Binary Tree
bin_tree.insert(20);
bin_tree.insert(30);
bin_tree.insert(52);
bin_tree.insert(254);
bin_tree.insert(2);
bin_tree.insert(24);
bin_tree.insert(25);
bin_tree.insert(42);
bin_tree.insert(59);
bin_tree.in_order_trav(); //in order traversal
bin_tree.pre_order_trav(); //pre order traversal
bin_tree.post_order_trav(); //post order traversal
}
The node value should be initialized(p->data = item) at function insert() as below
void bst::insert(int item) {
tree_node *p = new tree_node;
tree_node *parent;
p->left = NULL;
p->right = NULL;
p->data = item;
parent = NULL;
... ...
}
Ok the solution is silly! -.-
I forgot to add that line in insert routine!
p->data = item;
I have made a custom Stack and Queue class. In my program I want to use them both to test out if a word or phrase is a Palindrome. However, I need to change in my Stack and Queue class, which will allow both numbers and strings. How would I go about this in a simple manner? I read up on people having trouble using Palindromes but that is with the and C++ reference class. Any ideas? Here is my code which works with numbers.
//Queue.h
#include <iostream>
using namespace std;
class Queue
{
public:
Queue();
~Queue();
void enqueue(int);
int dequeue();
void print();
private:
typedef struct Node {
Node *link_;
int item_;
} NODE;
NODE* head_;
};
Queue::Queue()
{
head_ = NULL;
}
Queue::~Queue()
{
if (head_ == NULL) return;
NODE *cur = head_;
while (cur) {
Node *ptr = cur;
cur = cur->link_;
delete ptr;
}
}
void Queue::enqueue(int n)
{
if (head_ == NULL) {
head_ = new NODE;
head_->item_ = n;
head_->link_ = NULL;
return;
}
NODE *cur = head_;
while (cur) {
if (cur->link_ == NULL) {
NODE *ptr = new NODE;
ptr->item_ = n;
ptr->link_ = NULL;
cur->link_ = ptr;
return;
}
cur = cur->link_;
}
}
void Queue::print()
{
if (head_ == NULL) return;
Node *cur = head_;
cout << "This is your current queue: " << endl;
while (cur) {
cout << cur->item_ << " ";
cur = cur->link_;
}
cout << endl;
}
int Queue::dequeue()
{
if (head_ == NULL) {
cout << "This is an empty queue!!" << endl;
return NULL;
}
NODE *tmp = head_;
int value = head_->item_;
if (head_->link_) {
head_ = head_->link_;
}
// pop the last element (head)
else {
delete tmp;
head_ = NULL;
}
cout << "You dequeued: " << value << endl;;
return value;
}
int getQueue()
{
Queue *que = new Queue();
que->enqueue(15);
que->enqueue(75);
que->enqueue(105);
que->enqueue(25);
que->enqueue(55);
que->print();
que->dequeue(); que->print();
que->dequeue(); que->print();
que->dequeue(); que->print();
que->dequeue(); que->print();
que->dequeue(); que->print();
que->dequeue(); que->print();
return 0;
}
I am really new into coding for C++ and really want to learn. If anyone could help me out it'll be much appreciated.
The best way to do this is to make your Queue type templated
template <typename T> class Queue
{
public:
Queue();
~Queue();
void enqueue(const T &value);
T dequeue();
void print();
private:
typedef struct Node {
Node *link_;
T item_;
} NODE;
NODE* head_;
};
Now you can use it as
Queue<int> intQueue;
intQueue.enqueue(1);
intQueue.enqueue(2);
int i = intQueue.dequeue();
Queue<string> stringQueue;
stringQueue.enqueue("hello");
Queue<char> charQueue;
charQueue.enqueue('c');